Blocking signals causes boost process not to work

你离开我真会死。 提交于 2019-12-25 03:51:42

问题


In the code below the class Process can run a process using boost process in asynchronous mode and can kill it if it times out. Now in order to shut it down, I block all the signals in all threads and create a specific thread signal_thread to handle signals. On doing this the program stops working. I guess this is probably because the parent process can no longer receive the signal SIGCHLD and know that the child process has finished executing.

#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();
}

Please suggest how I can shut down the program using the signal handling thread as well make the program work correctly.


回答1:


Thinking more about it, I suggest blocking only signals that you intend for that signal thread to handle, such as SIGINT and 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);
        // ...
});


来源:https://stackoverflow.com/questions/52774591/blocking-signals-causes-boost-process-not-to-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!