diff --git a/webserv/client/Client.cpp b/webserv/client/Client.cpp index 694ada3..fb82294 100644 --- a/webserv/client/Client.cpp +++ b/webserv/client/Client.cpp @@ -1,6 +1,7 @@ #include "webserv/socket/Socket.hpp" #include #include +#include Client::Client(std::unique_ptr socket, Server &server, const ServerConfig &server_config) : client_socket_(std::move(socket)), server(std::ref(server)), server_config(std::cref(server_config)) @@ -9,7 +10,7 @@ Client::Client(std::unique_ptr socket, Server &server, const ServerConfi Client::~Client() { - std::cout << "Client destructor called for fd: " << client_socket_->getFd() << '\n'; + LOG_INFO("Client destructor called for fd: " + std::to_string(client_socket_->getFd())); server.removeFromEpoll(*client_socket_); }; @@ -17,7 +18,7 @@ int Client::parseHeaderforContentLength(const std::string &request) //NOLINT { std::string header = "Content-Length: "; size_t pos = request.find(header); - std::cout << "Parsing header for Content-Length...\n" << header << '\n'; + LOG_DEBUG("Parsing header for Content-Length...\n" + header); if (pos != std::string::npos) { size_t start = pos + header.length(); @@ -58,7 +59,7 @@ void Client::request() contentLength_ = parseHeaderforContentLength(header_); if (contentLength_ == -1) { - std::cout << "Received complete request:\n" << requestBuffer_ << "\n=== HEADER FINISHED\n"; + LOG_INFO("Received complete request:\n" + requestBuffer_ + "\n=== HEADER FINISHED\n"); server.responseReady(client_socket_->getFd()); } requestBuffer_.erase(0, headerEnd + 4); @@ -70,7 +71,7 @@ void Client::request() content_ += requestBuffer_; if (content_.size() >= contentLength_) { - std::cout << "Received complete request:\n" << header_ << content_ << "\n=== FULL REQUEST FINISHED\n"; + LOG_INFO("Received complete request:\n" + header_ + content_ + "\n=== FULL REQUEST FINISHED\n"); server.responseReady(client_socket_->getFd()); requestBuffer_.clear(); contentLength_ = -1; @@ -82,6 +83,6 @@ std::string Client::getResponse() const { std::string response = "HTTP/1.1 200 OK\r\nContent-Length: 32\r\n\r\nHello, World!"; response += " Server port " + std::to_string(server_config.getPort()) + "\r\n"; - std::cout << response << '\n'; + LOG_DEBUG("Sending response:\n" + response); return response; } \ No newline at end of file diff --git a/webserv/config/ConfigManager.cpp b/webserv/config/ConfigManager.cpp index e3c1264..0d1dc8b 100644 --- a/webserv/config/ConfigManager.cpp +++ b/webserv/config/ConfigManager.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -18,7 +19,6 @@ ConfigManager::~ConfigManager() ConfigManager &ConfigManager::getInstance() { static ConfigManager instance; - std::cout << "ConfigManager instance" << '\n'; return instance; } @@ -26,9 +26,10 @@ void ConfigManager::init(const std::string &filePath) { if (_initialized) { + LOG_WARN("ConfigManager is already initialized."); throw std::runtime_error("ConfigManager is already initialized."); } - std::cout << "Initializing ConfigManager with file: " << filePath << '\n'; + LOG_INFO("Initializing ConfigManager with file: " + filePath); parseConfigFile(filePath); _initialized = true; } @@ -70,7 +71,7 @@ void removeComments(std::string &str) void ConfigManager::parseConfigFile(const std::string &filePath) { // Placeholder for actual file parsing logic - std::cout << "Parsing configuration file: " << filePath << '\n'; + LOG_INFO("Parsing configuration file: " + filePath); // Implement the parsing logic here std::ifstream file(filePath); @@ -111,7 +112,7 @@ void ConfigManager::parseConfigFile(const std::string &filePath) } // parseGlobalDeclarations(globalDeclarations); // Implement this function to handle global config - std::cout << "Global Declarations:\n" << globalDeclarations << '\n'; + LOG_INFO("Global Declarations..."); file.close(); } diff --git a/webserv/config/LocationConfig.cpp b/webserv/config/LocationConfig.cpp index 20d3f45..4567e4d 100644 --- a/webserv/config/LocationConfig.cpp +++ b/webserv/config/LocationConfig.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -30,12 +31,12 @@ void LocationConfig::parseDirectives(const std::string &declarations) if (directive == "autoindex") { autoIndex = (value == "on"); - std::cout << "Set autoindex to " << (autoIndex ? "on" : "off") << '\n'; + LOG_INFO("Set autoindex to " + std::string(autoIndex ? "on" : "off")); } else if (directive == "index") { indexFile = value; - std::cout << "Set index file to " << indexFile << '\n'; + LOG_INFO("Set index file to " + indexFile); } else { diff --git a/webserv/config/ServerConfig.cpp b/webserv/config/ServerConfig.cpp index ac90454..dee9f77 100644 --- a/webserv/config/ServerConfig.cpp +++ b/webserv/config/ServerConfig.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -14,7 +15,7 @@ ServerConfig::ServerConfig(std::string const &serverBlock) : port(80) void ServerConfig::parseServerBlock(const std::string &block) { // Placeholder for actual server block parsing logic - std::cout << "Parsing server block:\n"; + LOG_INFO("Parsing server block..."); // Placeholder for actual file parsing logic @@ -42,7 +43,7 @@ void ServerConfig::parseServerBlock(const std::string &block) } // Optionally parse the server block here std::string locationBlock = block.substr(bracePos + 1, closeBrace - bracePos - 1); - std::cout << "Added location: " << locationPath << '\n'; + LOG_INFO("Added location: " + locationPath); locations.emplace(locationPath, locationBlock); pos = closeBrace + 1; } @@ -53,7 +54,7 @@ void ServerConfig::parseServerBlock(const std::string &block) void ServerConfig::parseDirectives(const std::string &declarations) { - std::cout << "Parsing server directives:\n"; + LOG_INFO("Parsing server directives" ); std::string line; std::istringstream stream(declarations); while (std::getline(stream, line)) @@ -73,27 +74,27 @@ void ServerConfig::parseDirectives(const std::string &declarations) { throw std::runtime_error("Invalid port number: " + std::to_string(port)); } - std::cout << "Set port to " << port << '\n'; + LOG_INFO("Set port to " + std::to_string(port)); } else if (directive == "root") { root = value; - std::cout << "Set root to " << root << '\n'; + LOG_INFO("Set root to " + root); } else if (directive == "host") { host = value; - std::cout << "Set host to " << host << '\n'; + LOG_INFO("Set host to " + host); } else if (directive == "cgi_pass") { cgi_pass = value; - std::cout << "Set cgi_pass to " << cgi_pass << '\n'; + LOG_INFO("Set cgi_pass to " + cgi_pass); } else if (directive == "cgi_ext") { cgi_ext = value; - std::cout << "Set cgi_ext to " << cgi_ext << '\n'; + LOG_INFO("Set cgi_ext to " + cgi_ext); } else if (directive == "index") { @@ -102,7 +103,7 @@ void ServerConfig::parseDirectives(const std::string &declarations) while (lineStream >> indexFile) { index_files.push_back(indexFile); - std::cout << "Added index file: " << indexFile << '\n'; + LOG_INFO("Added index file: " + indexFile); } } else if (directive == "error_page") @@ -111,11 +112,11 @@ void ServerConfig::parseDirectives(const std::string &declarations) std::string errorPagePath; lineStream >> errorPagePath; error_page[statusCode] = errorPagePath; - std::cout << "Set error_page for status " << statusCode << " to " << errorPagePath << '\n'; + LOG_INFO("Set error_page for status " + std::to_string(statusCode) + " to " + errorPagePath); } else { - std::cout << "Unknown directive: " << directive << '\n'; + LOG_WARN("Unknown directive: " + directive); } } } @@ -127,6 +128,7 @@ const LocationConfig &ServerConfig::getLocation(const std::string &path) const { return locations.at(path); } + LOG_ERROR("Location not found: " + path); throw std::runtime_error("Location not found: " + path); } diff --git a/webserv/log/Log.cpp b/webserv/log/Log.cpp index 90fa947..2343edc 100644 --- a/webserv/log/Log.cpp +++ b/webserv/log/Log.cpp @@ -1,5 +1,6 @@ #include "webserv/log/StdoutChannel.hpp" #include +#include Log::Log() { @@ -22,23 +23,63 @@ void Log::log(LogLevel level, const std::string &message, const std::string &cha it->second->log(level, message, context); } } +void Log::log(LogLevel level, const std::string &message, const std::string &file, int line, + const std::string &function, const std::string &channel, const std::map &context) +{ + auto it = channels_.find(channel); + if (it != channels_.end()) + { +std::string extendedMessage; + if (!file.empty()) + { + extendedMessage += std::filesystem::path(file).filename().string(); + } + if (line != -1) + { + extendedMessage += ":" + std::to_string(line); + } + if (!function.empty()) + { + extendedMessage += " (" + function + ")"; + } + extendedMessage += " | " + message; + it->second->log(level, extendedMessage, context); + } +} + +void Log::static_log(LogLevel level, const std::string &message, const std::string &file, int line, + const std::string &function, const std::string &channel, + const std::map &context) +{ + getInstance().log(level, message, file, line, function, channel, context); +} + +void Log::trace(const std::string &message, const std::map &context) +{ + getInstance().log(LogLevel::LOGLVL_TRACE, message, "stdout", context); +} void Log::debug(const std::string &message, const std::map &context) { - getInstance().log(LogLevel::DEBUG, message, "stdout", context); + getInstance().log(LogLevel::LOGLVL_DEBUG, message, "stdout", context); } void Log::info(const std::string &message, const std::map &context) { - getInstance().log(LogLevel::INFO, message, "stdout", context); + getInstance().log(LogLevel::LOGLVL_INFO, message, "stdout", context); } void Log::warning(const std::string &message, const std::map &context) { - getInstance().log(LogLevel::WARN, message, "stdout", context); + getInstance().log(LogLevel::LOGLVL_WARN, message, "stdout", context); } void Log::error(const std::string &message, const std::map &context) { - getInstance().log(LogLevel::ERROR, message, "stdout", context); + getInstance().log(LogLevel::LOGLVL_ERROR, message, "stdout", context); +} + +void Log::fatal(const std::string &message, const std::map &context) +{ + getInstance().log(LogLevel::LOGLVL_FATAL, message, "stdout", context); } \ No newline at end of file diff --git a/webserv/log/Log.hpp b/webserv/log/Log.hpp index d8a15b9..8a1d324 100644 --- a/webserv/log/Log.hpp +++ b/webserv/log/Log.hpp @@ -1,15 +1,21 @@ #pragma once -#include #include #include #include #include +#include #include +#define LOG(level, message) \ + Log::static_log((level), (message), __FILE__, __LINE__, __FUNCTION__, "stdout", {}) -#define LOG_INFO(message) \ - Log::info(message, std::map{{"file", __FILE__}, {"line", std::to_string(__LINE__)}, {"function", __FUNCTION__}}) +#define LOG_TRACE(message) LOG(LogLevel::LOGLVL_TRACE, message) +#define LOG_INFO(message) LOG(LogLevel::LOGLVL_INFO, message) +#define LOG_DEBUG(message) LOG(LogLevel::LOGLVL_DEBUG, message) +#define LOG_WARN(message) LOG(LogLevel::LOGLVL_WARN, message) +#define LOG_ERROR(message) LOG(LogLevel::LOGLVL_ERROR, message) +#define LOG_FATAL(message) LOG(LogLevel::LOGLVL_FATAL, message) class Channel; // Forward declaration @@ -24,10 +30,20 @@ class Log void log(LogLevel level, const std::string &message, const std::string &channel = "stdout", const std::map &context = {}); + void log(LogLevel level, const std::string &message, const std::string &file = "", int line = -1, + const std::string &function = "", const std::string &channel = "stdout", + const std::map &context = {}); + + static void static_log(LogLevel level, const std::string &message, const std::string &file = "", int line = -1, + const std::string &function = "", const std::string &channel = "stdout", + const std::map &context = {}); + + static void trace(const std::string &message, const std::map &context = {}); static void debug(const std::string &message, const std::map &context = {}); static void info(const std::string &message, const std::map &context = {}); static void warning(const std::string &message, const std::map &context = {}); static void error(const std::string &message, const std::map &context = {}); + static void fatal(const std::string &message, const std::map &context = {}); private: Log(); diff --git a/webserv/log/LogLevel.hpp b/webserv/log/LogLevel.hpp index 9314c4d..19d8d5a 100644 --- a/webserv/log/LogLevel.hpp +++ b/webserv/log/LogLevel.hpp @@ -5,24 +5,96 @@ enum class LogLevel : uint8_t { - DEBUG, - INFO, - WARN, - ERROR + LOGLVL_TRACE = 0, + LOGLVL_DEBUG = 1, + LOGLVL_INFO = 2, + LOGLVL_WARN = 3, + LOGLVL_ERROR = 4, + LOGLVL_FATAL = 5 }; +// ANSI color codes +namespace LogColors +{ +constexpr const char *RESET = "\033[0m"; +constexpr const char *TRACE_COLOR = "\033[36m"; // Cyan +constexpr const char *DEBUG_COLOR = "\033[90m"; // Bright black (gray) +constexpr const char *INFO_COLOR = "\033[37m"; // White +constexpr const char *WARN_COLOR = "\033[33m"; // Yellow +constexpr const char *ERROR_COLOR = "\033[31m"; // Red +constexpr const char *FATAL_COLOR = "\033[1;31m"; // Bold red +} // namespace LogColors + inline std::string logLevelToString(LogLevel level) { switch (level) { - case LogLevel::DEBUG: + case LogLevel::LOGLVL_TRACE: + return "TRACE"; + case LogLevel::LOGLVL_DEBUG: return "DEBUG"; - case LogLevel::INFO: + case LogLevel::LOGLVL_INFO: return "INFO"; - case LogLevel::WARN: + case LogLevel::LOGLVL_WARN: return "WARN"; - case LogLevel::ERROR: + case LogLevel::LOGLVL_ERROR: return "ERROR"; + case LogLevel::LOGLVL_FATAL: + return "FATAL"; } - return "UNKNOWN"; // Fallback to silence warnings + return "UNKNOWN"; +} + +inline const char *logLevelToColor(LogLevel level) +{ + switch (level) + { + case LogLevel::LOGLVL_TRACE: + return LogColors::TRACE_COLOR; + case LogLevel::LOGLVL_DEBUG: + return LogColors::DEBUG_COLOR; + case LogLevel::LOGLVL_INFO: + return LogColors::INFO_COLOR; + case LogLevel::LOGLVL_WARN: + return LogColors::WARN_COLOR; + case LogLevel::LOGLVL_ERROR: + return LogColors::ERROR_COLOR; + case LogLevel::LOGLVL_FATAL: + return LogColors::FATAL_COLOR; + } + return LogColors::RESET; +} + +inline std::string logLevelToColoredString(LogLevel level) +{ + return std::string(logLevelToColor(level)) + logLevelToString(level) + LogColors::RESET; +} + +inline LogLevel stringToLogLevel(const std::string &level) +{ + if (level == "TRACE") + { + return LogLevel::LOGLVL_TRACE; + } + if (level == "DEBUG") + { + return LogLevel::LOGLVL_DEBUG; + } + if (level == "INFO") + { + return LogLevel::LOGLVL_INFO; + } + if (level == "WARN") + { + return LogLevel::LOGLVL_WARN; + } + if (level == "ERROR") + { + return LogLevel::LOGLVL_ERROR; + } + if (level == "FATAL") + { + return LogLevel::LOGLVL_FATAL; + } + return LogLevel::LOGLVL_INFO; // Default fallback } \ No newline at end of file diff --git a/webserv/log/StdoutChannel.cpp b/webserv/log/StdoutChannel.cpp index 592e2c4..19dc3fb 100644 --- a/webserv/log/StdoutChannel.cpp +++ b/webserv/log/StdoutChannel.cpp @@ -5,7 +5,7 @@ void StdoutChannel::log(LogLevel &logLevel, const std::string &message, const std::map &context) { - std::string prefix = "[" + logLevelToString(logLevel) + "] "; + std::string prefix = "[" + logLevelToColoredString(logLevel) + "] "; std::cout << prefix; std::cout << message; if (!context.empty()) diff --git a/webserv/main.cpp b/webserv/main.cpp index b35a7f0..ee0294f 100644 --- a/webserv/main.cpp +++ b/webserv/main.cpp @@ -17,7 +17,13 @@ int main(int argc, char **argv) } ConfigManager::getInstance().init(argv[1]); // NOLINT Server server(ConfigManager::getInstance()); - LOG_INFO("HALLO WERELD!"); + LOG_TRACE("Trace message example."); + LOG_INFO("Info message example."); + LOG_DEBUG("Debug message example."); + LOG_WARN("Warning message example."); + LOG_ERROR("Error message example."); + LOG_FATAL("Fatal message example."); + Log::info("test log message: server starting...", {{"port", "8080"}, {"mode", "production"}}); server.start(); diff --git a/webserv/server/Server.cpp b/webserv/server/Server.cpp index 1d69c1e..0720ea1 100644 --- a/webserv/server/Server.cpp +++ b/webserv/server/Server.cpp @@ -11,16 +11,19 @@ #include // For close() #include #include +#include Server::Server(const ConfigManager &configManager) : epoll_fd_(epoll_create1(0)), configManager_(configManager) { const auto &serverConfigs = configManager.getServerConfigs(); if (serverConfigs.empty()) { + LOG_FATAL("No server configurations available."); throw std::runtime_error("No server configurations available."); } if (epoll_fd_ == -1) { + LOG_FATAL("epoll_create1 failed"); throw std::runtime_error("epoll_create1 failed"); } } @@ -35,7 +38,7 @@ Server::~Server() void Server::start() { - std::cout << "Starting servers...\n"; + LOG_INFO("Starting servers..."); // 1. Load server configurations for (const auto &config : configManager_.getServerConfigs()) @@ -44,6 +47,7 @@ void Server::start() } if (fdToConfig_.empty()) { + LOG_FATAL("No server sockets created."); throw std::runtime_error("No server sockets created."); } @@ -58,6 +62,7 @@ void Server::addToEpoll(const Socket &socket, uint32_t events) const event.data.fd = fd; if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event) == -1) { + LOG_ERROR("epoll_ctl ADD failed for fd: " + std::to_string(fd)); throw std::runtime_error("epoll_ctl ADD failed"); } } @@ -67,6 +72,7 @@ void Server::removeFromEpoll(const Socket &socket) const int filedes = socket.getFd(); if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, filedes, nullptr) == -1) { + LOG_ERROR("epoll_ctl DEL failed for fd: " + std::to_string(filedes)); throw std::runtime_error("epoll_ctl DEL failed"); } } @@ -84,11 +90,11 @@ void Server::setupServerSocket(const ServerConfig &config) listeners_.push_back(std::move(serverSocket)); fdToConfig_.insert({server_fd, std::cref(config)}); - std::cout << "Server listening on " << config.getHost() << ":" << config.getPort() << "...\n"; + LOG_INFO("Server listening on " + config.getHost() + ":" + std::to_string(config.getPort()) + "..."); } catch (const std::exception &e) { - std::cerr << "Error setting up server socket: " << e.what() << '\n'; + LOG_ERROR("Error setting up server socket: " + std::string(e.what())); } } @@ -110,6 +116,7 @@ Socket &Server::getListener(int fd) const return *listener; } } + LOG_ERROR("Listener not found for fd: " + std::to_string(fd)); throw std::runtime_error("Listener not found for fd: " + std::to_string(fd)); } @@ -120,6 +127,7 @@ Client &Server::getClient(int fd) const { return *(it->second); } + LOG_ERROR("Client not found for fd: " + std::to_string(fd)); throw std::runtime_error("Client not found for fd: " + std::to_string(fd)); } @@ -135,6 +143,7 @@ const ServerConfig &Server::getConfig(int fd) const { return (it->second.get()); } + LOG_ERROR("Config not found for fd: " + std::to_string(fd)); throw std::runtime_error("Config not found for fd: " + std::to_string(fd)); } @@ -148,19 +157,20 @@ void Server::handleRequest(struct epoll_event *event) const void Server::responseReady(int client_fd) const { - std::cout << "Response ready for client fd: " << client_fd << '\n'; + LOG_INFO("Response ready for client fd: " + std::to_string(client_fd)); struct epoll_event ev{}; ev.events = EPOLLOUT; ev.data.fd = client_fd; if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, client_fd, &ev) == -1) { + LOG_ERROR("epoll_ctl MOD failed for fd: " + std::to_string(client_fd)); throw std::runtime_error("epoll_ctl MOD failed"); } } void Server::eventLoop() { - std::cout << "Entering event loop...\n"; + LOG_INFO("Entering event loop..."); const int MAX_EVENTS = 10; struct epoll_event events[MAX_EVENTS]; // NOLINT while (true) @@ -168,6 +178,7 @@ void Server::eventLoop() int nfds = epoll_wait(epoll_fd_, events, MAX_EVENTS, -1); // NOLINT if (nfds == -1) { + LOG_ERROR("epoll_wait failed"); throw std::runtime_error("epoll_wait failed"); } for (int i = 0; i < nfds; ++i) @@ -175,7 +186,7 @@ void Server::eventLoop() epoll_event &event = events[i]; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) if ((event.events & EPOLLERR) > 0 || (event.events & EPOLLHUP) > 0) { - std::cerr << "Epoll error on fd " << event.data.fd << '\n'; + LOG_ERROR("Epoll error on fd " + std::to_string(event.data.fd)); removeFromEpoll(getListener(event.data.fd)); close(event.data.fd); } @@ -189,14 +200,19 @@ void Server::eventLoop() } else if ((event.events & EPOLLOUT) > 0) { - std::cout << "Attempting to send data to fd: " << event.data.fd << '\n'; + LOG_INFO("Attempting to send data to fd: " + std::to_string(event.data.fd)); Client &client = getClient(event.data.fd); std::string response = client.getResponse(); const char *httpResponse = response.c_str(); ssize_t bytesSent = send(event.data.fd, httpResponse, strlen(httpResponse), 0); if (bytesSent < 0) { - perror("Send error"); + LOG_ERROR("Send failed for fd: " + std::to_string(event.data.fd) + " with error: " + std::strerror(errno)); + + } + else + { + LOG_INFO("Sent " + std::to_string(bytesSent) + " bytes to fd: " + std::to_string(event.data.fd)); } clients_.erase(event.data.fd); } diff --git a/webserv/socket/Socket.cpp b/webserv/socket/Socket.cpp index f065142..acd04f2 100644 --- a/webserv/socket/Socket.cpp +++ b/webserv/socket/Socket.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include // For close() @@ -13,6 +14,7 @@ Socket::Socket() : _fd(socket(AF_INET, SOCK_STREAM, 0)) { if (_fd == -1) { + LOG_ERROR("Socket creation failed"); throw std::runtime_error("Socket creation failed"); } int opt = 1; @@ -20,6 +22,7 @@ Socket::Socket() : _fd(socket(AF_INET, SOCK_STREAM, 0)) { close(_fd); _fd = -1; + LOG_ERROR("setsockopt failed"); throw std::runtime_error("setsockopt failed"); } setNonBlocking(); @@ -29,6 +32,7 @@ Socket::Socket(int fd) : _fd(fd) // NOLINT(readability-identifier-naming) { if (_fd == -1) { + LOG_ERROR("Invalid file descriptor"); throw std::runtime_error("Invalid file descriptor"); } setNonBlocking(); @@ -46,6 +50,7 @@ void Socket::listen(int backlog) const { if (::listen(_fd, backlog) < 0) { + LOG_ERROR("Listen failed"); throw std::runtime_error("Listen failed"); } } @@ -68,6 +73,7 @@ std::unique_ptr Socket::accept() const int client_fd = ::accept(_fd, nullptr, nullptr); if (client_fd < 0) { + LOG_ERROR("Accept failed"); throw std::runtime_error("Accept failed"); } return std::make_unique(client_fd); @@ -87,6 +93,7 @@ void Socket::setNonBlocking() const { if (fcntl(_fd, F_SETFL, O_NONBLOCK) < 0) { + LOG_ERROR("Failed to set non-blocking mode"); throw std::runtime_error("Failed to set non-blocking mode"); } }