В приведенном ниже коде класс 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();
}
Пожалуйста, предложите, как я могу закрыть программу, используя поток обработки сигналов, а также заставить программу работать правильно.