From 60405f03d572fe7b6c3dcef101e487706e0ff240 Mon Sep 17 00:00:00 2001 From: whaffman Date: Fri, 17 Oct 2025 16:28:04 +0200 Subject: [PATCH] feat: implement CGI process management with wait and kill functionality --- webserv/client/Client.cpp | 9 +++++++++ webserv/client/Client.hpp | 3 --- webserv/handler/CgiHandler.cpp | 15 +++++++++++++++ webserv/handler/CgiHandler.hpp | 4 ++++ webserv/handler/CgiProcess.cpp | 34 ++++++++++++++++++++++++++++++++++ webserv/handler/CgiProcess.hpp | 2 ++ 6 files changed, 64 insertions(+), 3 deletions(-) diff --git a/webserv/client/Client.cpp b/webserv/client/Client.cpp index bebe8e7..54beb50 100644 --- a/webserv/client/Client.cpp +++ b/webserv/client/Client.cpp @@ -1,3 +1,4 @@ +#include "webserv/handler/CgiHandler.hpp" #include "webserv/socket/ASocket.hpp" #include "webserv/socket/CgiSocket.hpp" @@ -118,12 +119,20 @@ void Client::removeCgiSocket(CgiSocket *cgiSocket) void Client::poll() const { + auto * cgiHandler = dynamic_cast(handler_.get()); + if (cgiHandler != nullptr) + { + Log::debug("Polling CGI handler for client, fd: " + std::to_string(clientSocket_->getFd())); + // CGI handler polling logic if needed + cgiHandler->wait(); + } if (httpResponse_->isComplete()) { Log::info("Response is ready to be sent to client, fd: " + std::to_string(clientSocket_->getFd())); clientSocket_->setCallback([this]() { respond(); }); server_.writable(clientSocket_->getFd()); } + } void Client::respond() const diff --git a/webserv/client/Client.hpp b/webserv/client/Client.hpp index 1a09c2f..8323704 100644 --- a/webserv/client/Client.hpp +++ b/webserv/client/Client.hpp @@ -57,9 +57,6 @@ class Client std::unique_ptr router_; std::unique_ptr handler_ = nullptr; std::unique_ptr clientSocket_; - std::unique_ptr cgiStdIn_ = nullptr; - std::unique_ptr cgiStdOut_ = nullptr; - std::unordered_map sockets_; Server &server_; diff --git a/webserv/handler/CgiHandler.cpp b/webserv/handler/CgiHandler.cpp index 2431dc4..21d8eff 100644 --- a/webserv/handler/CgiHandler.cpp +++ b/webserv/handler/CgiHandler.cpp @@ -19,6 +19,7 @@ void CgiHandler::handle() // Initialize CGI process cgiProcess_ = std::make_unique(request_, *this); + Log::info("CGI process started and sockets registered"); } @@ -95,4 +96,18 @@ void CgiHandler::setCgiSockets(std::unique_ptr cgiStdIn, std::unique_ request_.getClient().setCgiSockets(cgiStdIn_.get(), cgiStdOut_.get()); // write // TODO add to handler +} + +void CgiHandler::wait() noexcept +{ + if (cgiProcess_) + { + cgiProcess_->wait(); + } +} + +void CgiHandler::setPid(int pid) +{ + pid_ = pid; + } \ No newline at end of file diff --git a/webserv/handler/CgiHandler.hpp b/webserv/handler/CgiHandler.hpp index c507af0..602d5eb 100644 --- a/webserv/handler/CgiHandler.hpp +++ b/webserv/handler/CgiHandler.hpp @@ -20,13 +20,17 @@ class CgiHandler : public AHandler ~CgiHandler() = default; void handle() override; + void wait() noexcept; void setCgiSockets(std::unique_ptr cgiStdIn, std::unique_ptr cgiStdOut); + void setPid(int pid); private: constexpr static size_t bufferSize_ = 8192; // TODO: remove duplicate definition and move to configmanager std::unique_ptr cgiProcess_; std::unique_ptr cgiStdIn_; std::unique_ptr cgiStdOut_; + int pid_ = -1; + void write(); void read(); diff --git a/webserv/handler/CgiProcess.cpp b/webserv/handler/CgiProcess.cpp index cd30c68..5a25bb5 100644 --- a/webserv/handler/CgiProcess.cpp +++ b/webserv/handler/CgiProcess.cpp @@ -11,6 +11,8 @@ #include #include +#include +#include CgiProcess::CgiProcess(const HttpRequest &request, CgiHandler &handler) : request_(request), handler_(handler), _pid(-1) { @@ -81,5 +83,37 @@ void CgiProcess::spawn() // request_.getClient().setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut)); // move the sockets to the // client handler_.setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut)); + handler_.setPid(_pid); + } +} + +void CgiProcess::kill() const noexcept +{ + if (_pid > 0) + { + ::kill(_pid, SIGKILL); + Log::debug("Killed CGI process with PID: " + std::to_string(_pid)); + } +} + +void CgiProcess::wait() noexcept +{ + if (_pid > 0) + { + int status; + int waitResult =::waitpid(_pid, &status, WNOHANG); + if (waitResult == -1) + { + Log::error("Error while waiting for CGI process with PID: " + std::to_string(_pid)); + return; + } + if (waitResult == 0) + { + // Still running + return; + } + + Log::debug("CGI process with PID " + std::to_string(_pid) + " has terminated"); + _pid = -1; } } \ No newline at end of file diff --git a/webserv/handler/CgiProcess.hpp b/webserv/handler/CgiProcess.hpp index c90b9e3..98bde3a 100644 --- a/webserv/handler/CgiProcess.hpp +++ b/webserv/handler/CgiProcess.hpp @@ -15,6 +15,8 @@ class CgiProcess CgiProcess &operator=(CgiProcess &&other) noexcept = delete; ~CgiProcess() = default; + void kill() const noexcept; + void wait() noexcept; private: const HttpRequest &request_;