/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* FileDescriptor.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: acossari +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/08/24 16:24:03 by acossari #+# #+# */ /* Updated: 2026/08/24 20:05:59 by acossari ### ########.fr */ /* */ /* ************************************************************************** */ #pragma once #include #include namespace webserv { // Sole owner of one file descriptor, move-only. Copying would give two owners // the same number, and the second close would land on whatever the kernel had // handed out in the meantime, killing an unrelated connection. class FileDescriptor final { public: class Error : public std::exception { public: explicit Error(std::string message); const char* what() const noexcept override; private: std::string msg_; }; FileDescriptor() = default; // Takes ownership and sets FD_CLOEXEC, so a successful execve() in a // forked child closes the descriptor before the new program starts. A // negative fd is accepted and gives an invalid object instead of throwing, // so the result of socket() can be passed in and checked with valid(). explicit FileDescriptor(int fd); ~FileDescriptor(); FileDescriptor(const FileDescriptor&) = delete; FileDescriptor& operator=(const FileDescriptor&) = delete; FileDescriptor(FileDescriptor&& other) noexcept; FileDescriptor& operator=(FileDescriptor&& other) noexcept; int get() const noexcept { return fd_; } bool valid() const noexcept { return fd_ >= 0; } void setNonBlocking(); // Closes now instead of at destruction. Idempotent. void reset() noexcept; private: int fd_ = -1; }; } // namespace webserv