From 702d32b41c1c4f496dba046c2017cb5b907e55cd Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Thu, 12 Jan 2023 20:00:40 +0100 Subject: FCGI test --- tests/fastcgiprocess.cpp | 115 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 tests/fastcgiprocess.cpp (limited to 'tests/fastcgiprocess.cpp') diff --git a/tests/fastcgiprocess.cpp b/tests/fastcgiprocess.cpp new file mode 100644 index 0000000..53b9d04 --- /dev/null +++ b/tests/fastcgiprocess.cpp @@ -0,0 +1,115 @@ +#include "fastcgiprocess.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "helper.h" + +using namespace std::string_literals; +namespace fs = std::filesystem; +namespace pt = boost::property_tree; +using namespace boost::unit_test; +using namespace Reichwein; + +#define FCGI_LISTENSOCK_FILENO 0 + +FastCGIProcess::FastCGIProcess(const std::filesystem::path& path, const std::string& host, unsigned short port): + m_pid{}, + m_command{path.generic_string()}, + m_host{host}, + m_port{port} +{ + start(); +} + +FastCGIProcess::~FastCGIProcess() +{ + stop(); +} + +void FastCGIProcess::start() +{ + if (m_pid != 0) + throw std::runtime_error("Process already running, so it can't be started"); + + m_pid = fork(); + if (m_pid < 0) + throw std::runtime_error("Fork unsuccessful."); + + if (m_pid == 0) { // child process branch + try { + boost::asio::io_context ioc; + boost::asio::ip::tcp::resolver resolver(ioc); + auto const results = resolver.resolve(m_host.c_str(), std::to_string(m_port).c_str()); + if (results.begin() == results.end()) + std::runtime_error("no resolve result"); + boost::asio::ip::tcp::endpoint endpoint{*results.begin()}; + boost::asio::ip::tcp::acceptor acceptor(ioc); + acceptor.open(endpoint.protocol()); + acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + acceptor.bind(endpoint); + acceptor.listen(); + int fd{acceptor.native_handle()}; + + if (fd != FCGI_LISTENSOCK_FILENO) { + close(FCGI_LISTENSOCK_FILENO); + dup2(fd, FCGI_LISTENSOCK_FILENO); + close(fd); + } + + execl(m_command.c_str(), m_command.c_str(), (const char*)nullptr); + } catch (const std::exception& ex) { + std::cout << "FastCGI process error: " << ex.what() << std::endl; + } + exit(0); + } + + // wait for server to start up + wait_for_pid_listening_on(m_pid, m_port); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); +} + +void FastCGIProcess::stop() +{ + if (m_pid == 0) + throw std::runtime_error("Process not running, so it can't be stopped"); + + if (kill(m_pid, SIGTERM) != 0) + throw std::runtime_error("Unable to kill process"); + + if (int result = waitpid(m_pid, NULL, 0); result != m_pid) + throw std::runtime_error("waitpid returned "s + std::to_string(result)); + + m_pid = 0; +} + +bool FastCGIProcess::is_running() +{ + if (m_pid == 0) + return false; + + return Reichwein::Process::is_running(m_pid); +} + -- cgit v1.2.3