信号处理程序不适用于通过管道打开的进程

时间:2019-07-13 02:38:48

标签: c++ pipe signals

注意:这是一个常见问题(不限于wolfram命令,您不必了解wolfram)。

我考虑包装wolfram(CUI计算器,例如python解释器)。没有任何包装,SIGINT会导致程序暂停计算。

$ /usr/bin/wolfram -noinit

In[1] := While[True, 1] #start infinite loop
#execute `kill -SIGINT` from another shell to send SIGINT
Interrupt> #calculation now interrupted (you can cancel or resume it)

但是,SIGINT使用包装器会导致wolfram立即退出。

$ ./wrapper.out

In[1] := While[True, 1] #start infinite loop
#execute `kill -SIGINT` (the target is not the wrapper but the `wolfram` itself)   
#`wolfram` exits right away
Caught SIGPIPE. #the wrapper recieves SIGPIPE

包装的完整代码在这里。 (在没有exit(0)和智能指针的情况下,实际代码编写得更好,但是下面的简化代码仍然会引起问题。)

using namespace std;
#include <iostream>
#include <csignal>

void signal_handler(int signal) {
    if (signal == SIGINT) {
        cout << "Caught SIGINT.\n";
    } else {
        cout << "Caught SIGPIPE.\n";
    }
    exit(0); //not good since destructors aren't called
}

int main(int argc, char **argv) {

    //set a signal handler
    signal(SIGINT, signal_handler);
    signal(SIGPIPE, signal_handler);

    FILE *pipe = popen("/usr/bin/wolfram -noinit", "w");

    while (true) {

        string buf;
        getline(cin, buf);

        fprintf(pipe, "%s\n", buf.c_str());
        fflush(pipe);

    }

    pclose(pipe);

}

为什么使用包装程序会忽略管道处理的信号处理程序?以及如何保留原始信号处理程序的功能? man 3 popen没有给我任何提示。

0 个答案:

没有答案