Блокировка сигналов приводит к тому, что процесс наддува не работает

В коде ниже класса Process может запустить процесс, используя boost process в асинхронном режиме и может убить его, если время ожидания истекло. Теперь, чтобы выключить его, я блокирую все сигналы во всех потоках и создаю специальный поток signal_thread для обработки сигналов. После этого программа перестает работать. Я думаю, это потому, что родительский процесс больше не может получать сигнал SIGCHLD и знать, что дочерний процесс завершил выполнение.

#include <iostream>
#include <csignal>
#include <thread>
#include <chrono>
#include <future>
#include <boost/process.hpp>
#include <boost/asio.hpp>

namespace bp = boost::process;
std::atomic<bool> stop(false);
class Process
{
public:
Process(const std::string& cmd, const int timeout);
void run();

private:
void timeoutHandler(const boost::system::error_code& ec);
void kill();

const std::string command;
const int timeout;
bool stopped;
boost::process::group group;
boost::asio::io_context ioc;
boost::asio::deadline_timer deadline_timer;
unsigned returnStatus;
};

Process::Process(const std::string& cmd, const int timeout):
command(cmd),
timeout(timeout),
stopped(false),
ioc(),
deadline_timer(ioc),
returnStatus(0)
{}

void Process::timeoutHandler(const boost::system::error_code& ec)
{
if (stopped || ec == boost::asio::error::operation_aborted)
{
return;
}

std::cout << "Time Up!" << std::endl;
kill();
deadline_timer.expires_at(boost::posix_time::pos_infin);
}

void Process::run()
{
std::future<std::string> dataOut;
std::future<std::string> dataErr;
std::cout << "Running command: "<< command << std::endl;
bp::child c(command, bp::std_in.close(),
bp::std_out > dataOut,
bp::std_err > dataErr, ioc,
group,
bp::on_exit([=](int e, const std::error_code& ec) {
std::cout << "on_exit: " << ec.message() << " -> "<< e << std::endl;
deadline_timer.cancel();
returnStatus = e;
}));

deadline_timer.expires_from_now(boost::posix_time::seconds(timeout));
deadline_timer.async_wait(std::bind(&Process::timeoutHandler, this, std::placeholders::_1));

ioc.run();
c.wait();
std::cout << "returnStatus "<< returnStatus << std::endl;
std::cout << "stdOut "<< dataOut.get() << std::endl;
std::cout << "stdErr "<< dataErr.get() << std::endl;
}

void Process::kill()
{
std::error_code ec;
group.terminate(ec);
if(ec)
{
std::cerr << "Error occurred while trying to kill the process: " << ec.message() << std::endl;
throw std::runtime_error(ec.message());
}
std::cout << "Killed the process and all its descendants" << std::endl;
stopped = true;
}

void myfunction()
{
while(true)
{
Process p("date", 3600);
p.run();
std::this_thread::sleep_for(std::chrono::milliseconds(3000));

if(stop)
break;
}
}

int main() {
sigset_t sigset;
sigfillset(&sigset);
::pthread_sigmask(SIG_BLOCK, &sigset, nullptr);

std::thread signal_thread([]() {
while(true)
{
sigset_t sigset;
sigfillset(&sigset);
int signo = ::sigwaitinfo(&sigset, nullptr);
if(-1 == signo)
std::abort();

std::cout << "Received signal " << signo << '\n';
if(signo != SIGCHLD)
{
break;
}
}
stop = true;
});

myfunction();

signal_thread.join();
}

Пожалуйста, предложите, как я могу закрыть программу, используя поток обработки сигналов, а также заставить программу работать правильно.

0

Решение

Подумав больше об этом, я предлагаю блокировать только те сигналы, которые вы собираетесь обработать для этого потока сигналов, например: SIGINT а также SIGTERM:

sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
::pthread_sigmask(SIG_BLOCK, &sigset, nullptr);

std::thread signal_thread([sigset]() { // Use the same sigset.
// ...
int signo = ::sigwaitinfo(&sigset, nullptr);
// ...
});
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]