feat: implement CGI process management with wait and kill functionality

This commit is contained in:
whaffman 2025-10-17 16:28:04 +02:00
parent b8e3e16f3d
commit 60405f03d5
6 changed files with 64 additions and 3 deletions

View File

@ -1,3 +1,4 @@
#include "webserv/handler/CgiHandler.hpp"
#include "webserv/socket/ASocket.hpp" #include "webserv/socket/ASocket.hpp"
#include "webserv/socket/CgiSocket.hpp" #include "webserv/socket/CgiSocket.hpp"
@ -118,12 +119,20 @@ void Client::removeCgiSocket(CgiSocket *cgiSocket)
void Client::poll() const void Client::poll() const
{ {
auto * cgiHandler = dynamic_cast<CgiHandler *>(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()) if (httpResponse_->isComplete())
{ {
Log::info("Response is ready to be sent to client, fd: " + std::to_string(clientSocket_->getFd())); Log::info("Response is ready to be sent to client, fd: " + std::to_string(clientSocket_->getFd()));
clientSocket_->setCallback([this]() { respond(); }); clientSocket_->setCallback([this]() { respond(); });
server_.writable(clientSocket_->getFd()); server_.writable(clientSocket_->getFd());
} }
} }
void Client::respond() const void Client::respond() const

View File

@ -57,9 +57,6 @@ class Client
std::unique_ptr<Router> router_; std::unique_ptr<Router> router_;
std::unique_ptr<AHandler> handler_ = nullptr; std::unique_ptr<AHandler> handler_ = nullptr;
std::unique_ptr<ClientSocket> clientSocket_; std::unique_ptr<ClientSocket> clientSocket_;
std::unique_ptr<CgiSocket> cgiStdIn_ = nullptr;
std::unique_ptr<CgiSocket> cgiStdOut_ = nullptr;
std::unordered_map<int, ASocket *> sockets_; std::unordered_map<int, ASocket *> sockets_;
Server &server_; Server &server_;

View File

@ -19,6 +19,7 @@ void CgiHandler::handle()
// Initialize CGI process // Initialize CGI process
cgiProcess_ = std::make_unique<CgiProcess>(request_, *this); cgiProcess_ = std::make_unique<CgiProcess>(request_, *this);
Log::info("CGI process started and sockets registered"); Log::info("CGI process started and sockets registered");
} }
@ -96,3 +97,17 @@ void CgiHandler::setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_
// TODO add to handler // TODO add to handler
} }
void CgiHandler::wait() noexcept
{
if (cgiProcess_)
{
cgiProcess_->wait();
}
}
void CgiHandler::setPid(int pid)
{
pid_ = pid;
}

View File

@ -20,13 +20,17 @@ class CgiHandler : public AHandler
~CgiHandler() = default; ~CgiHandler() = default;
void handle() override; void handle() override;
void wait() noexcept;
void setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_ptr<CgiSocket> cgiStdOut); void setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_ptr<CgiSocket> cgiStdOut);
void setPid(int pid);
private: private:
constexpr static size_t bufferSize_ = 8192; // TODO: remove duplicate definition and move to configmanager constexpr static size_t bufferSize_ = 8192; // TODO: remove duplicate definition and move to configmanager
std::unique_ptr<CgiProcess> cgiProcess_; std::unique_ptr<CgiProcess> cgiProcess_;
std::unique_ptr<CgiSocket> cgiStdIn_; std::unique_ptr<CgiSocket> cgiStdIn_;
std::unique_ptr<CgiSocket> cgiStdOut_; std::unique_ptr<CgiSocket> cgiStdOut_;
int pid_ = -1;
void write(); void write();
void read(); void read();

View File

@ -11,6 +11,8 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h>
#include <csignal>
CgiProcess::CgiProcess(const HttpRequest &request, CgiHandler &handler) : request_(request), handler_(handler), _pid(-1) 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 // request_.getClient().setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut)); // move the sockets to the
// client // client
handler_.setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut)); 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;
} }
} }

View File

@ -15,6 +15,8 @@ class CgiProcess
CgiProcess &operator=(CgiProcess &&other) noexcept = delete; CgiProcess &operator=(CgiProcess &&other) noexcept = delete;
~CgiProcess() = default; ~CgiProcess() = default;
void kill() const noexcept;
void wait() noexcept;
private: private:
const HttpRequest &request_; const HttpRequest &request_;