feat(CgiHandler, TimerSocket): enhance error handling and add read/write methods
This commit is contained in:
parent
cd33bb1ce6
commit
656abd24e7
@ -140,7 +140,7 @@ 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()));
|
||||
// Log::debug("Polling CGI handler for client, fd: " + std::to_string(clientSocket_->getFd()));
|
||||
// CGI handler polling logic if needed
|
||||
cgiHandler->wait();
|
||||
}
|
||||
|
||||
@ -58,9 +58,9 @@ class Client
|
||||
std::unique_ptr<HttpRequest> httpRequest_;
|
||||
std::unique_ptr<HttpResponse> httpResponse_;
|
||||
std::unique_ptr<Router> router_;
|
||||
std::unique_ptr<AHandler> handler_ = nullptr;
|
||||
std::unique_ptr<ClientSocket> clientSocket_;
|
||||
std::unordered_map<int, ASocket *> sockets_;
|
||||
std::unique_ptr<AHandler> handler_ = nullptr;
|
||||
|
||||
Server &server_;
|
||||
void writeToCgi();
|
||||
|
||||
@ -10,6 +10,10 @@
|
||||
|
||||
AHandler::AHandler(const HttpRequest &request, HttpResponse &response) : request_(request), response_(response) {}
|
||||
|
||||
AHandler::~AHandler()
|
||||
{
|
||||
cancelTimer();
|
||||
}
|
||||
void AHandler::startTimer()
|
||||
{
|
||||
timerSocket_ = std::make_unique<TimerSocket>(std::chrono::milliseconds(5000));
|
||||
|
||||
@ -10,7 +10,7 @@ class AHandler
|
||||
{
|
||||
public:
|
||||
AHandler(const HttpRequest &request, HttpResponse &response);
|
||||
virtual ~AHandler() = default;
|
||||
virtual ~AHandler();
|
||||
|
||||
AHandler(const AHandler &other) = delete;
|
||||
AHandler &operator=(const AHandler &other) = delete;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include "webserv/handler/ErrorHandler.hpp"
|
||||
|
||||
#include <webserv/client/Client.hpp> // for Client
|
||||
#include <webserv/handler/CgiHandler.hpp>
|
||||
#include <webserv/handler/CgiProcess.hpp> // for CgiProcess
|
||||
@ -8,6 +9,8 @@
|
||||
#include <webserv/socket/CgiSocket.hpp> // for CgiSocket
|
||||
#include <webserv/utils/utils.hpp> // for stoul
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
CgiHandler::CgiHandler(const HttpRequest &request, HttpResponse &response)
|
||||
: AHandler(request, response), cgiProcess_(nullptr), cgiStdIn_(nullptr), cgiStdOut_(nullptr)
|
||||
{
|
||||
@ -74,7 +77,7 @@ void CgiHandler::read()
|
||||
{
|
||||
Log::info("CGI process closed stdout, fd: " + std::to_string(cgiStdOut_->getFd()));
|
||||
request_.getClient().removeSocket(cgiStdOut_.get());
|
||||
request_.getClient().removeSocket(timerSocket_.get());
|
||||
// request_.getClient().removeSocket(timerSocket_.get());
|
||||
cgiStdOut_ = nullptr;
|
||||
parseCgiOutput();
|
||||
return;
|
||||
@ -107,19 +110,20 @@ void CgiHandler::error()
|
||||
{
|
||||
Log::info("CGI process closed stderr, fd: " + std::to_string(cgiStdErr_->getFd()));
|
||||
request_.getClient().removeSocket(cgiStdErr_.get());
|
||||
request_.getClient().removeSocket(timerSocket_.get()); // todo maybe this dangerous
|
||||
// request_.getClient().removeSocket(timerSocket_.get()); // todo maybe this dangerous
|
||||
cgiStdErr_ = nullptr;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[bytesRead] = '\0'; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
|
||||
Log::error("CGI stderr output (fd: " + std::to_string(cgiStdErr_->getFd()) + "): "
|
||||
+ std::string(buffer, static_cast<size_t>(bytesRead)));
|
||||
Log::error("CGI stderr output (fd: " + std::to_string(cgiStdErr_->getFd())
|
||||
+ "): " + std::string(buffer, static_cast<size_t>(bytesRead)));
|
||||
}
|
||||
}
|
||||
|
||||
void CgiHandler::setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_ptr<CgiSocket> cgiStdOut, std::unique_ptr<CgiSocket> cgiStdErr)
|
||||
void CgiHandler::setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_ptr<CgiSocket> cgiStdOut,
|
||||
std::unique_ptr<CgiSocket> cgiStdErr)
|
||||
{
|
||||
cgiStdIn->setCallback([this]() { write(); });
|
||||
cgiStdOut->setCallback([this]() { read(); });
|
||||
@ -221,7 +225,14 @@ void CgiHandler::parseCgiHeaders(std::string &headers)
|
||||
void CgiHandler::handleTimeout()
|
||||
{
|
||||
Log::warning("CGI handler timeout occurred for PID: " + std::to_string(pid_));
|
||||
|
||||
char buffer[9] = {}; // NOLINT(cppcoreguidelines-avoid-c-arrays)
|
||||
ssize_t bytesRead = timerSocket_->read(buffer, sizeof(buffer) - 1);
|
||||
buffer[bytesRead] = '\0';
|
||||
if (bytesRead <= 0)
|
||||
{
|
||||
// NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
|
||||
return;
|
||||
}
|
||||
// Terminate the CGI process if it's still running
|
||||
if (cgiProcess_)
|
||||
{
|
||||
|
||||
@ -44,3 +44,25 @@ bool TimerSocket::isActive() const noexcept
|
||||
{
|
||||
return active_;
|
||||
}
|
||||
|
||||
ssize_t TimerSocket::read(void *buf, size_t len) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
ssize_t bytesRead = ::read(getFd(), buf, len);
|
||||
if (bytesRead == -1)
|
||||
{
|
||||
throw std::system_error(errno, std::generic_category(), "Socket: Read error");
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
ssize_t TimerSocket::write(const void *buf, size_t len) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
ssize_t bytesSent = ::write(getFd(), buf, len);
|
||||
if (bytesSent == -1)
|
||||
{
|
||||
throw std::system_error(errno, std::generic_category(), "Socket: Write error");
|
||||
}
|
||||
return bytesSent;
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "webserv/socket/ASocket.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
class TimerSocket : public ASocket
|
||||
@ -11,7 +12,11 @@ class TimerSocket : public ASocket
|
||||
[[nodiscard]] ASocket::Type getType() const noexcept override;
|
||||
[[nodiscard]] bool isActive() const noexcept;
|
||||
|
||||
ssize_t read(void *buf, size_t len) const override;
|
||||
ssize_t write(const void *buf, size_t len) const override;
|
||||
|
||||
void activate();
|
||||
|
||||
private:
|
||||
bool active_ = false;
|
||||
std::chrono::milliseconds timeout_;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user