调用system时忽略SIGINT(3)

时间:2019-10-23 20:24:40

标签: c++ linux

我有一个带有线程的进程,该线程例如循环调用system("ping -qnc 1 192.168.1.1")
当我执行 CTRL + C 时,根据文档将忽略SIGINT:

  

在执行命令期间,SIGCHLD将被阻止,SIGINT和   SIGQUIT在调用system()的过程中将被忽略(这些信号将在执行 command 的子过程中根据其缺省值进行处理)。

这是为什么,如何使用 CTRL + C 退出我的进程?

3 个答案:

答案 0 :(得分:2)

您的进程已阻止了这些信号,因此当用户按下Ctrl-C ping时将被杀死,而您的程序也未被杀死。

如果您想要要被杀死的程序,则可以检查system()的返回值,并查看ping是否由于信号而被杀死。如果是这样,您可以采取适当的措施。

int status = system("ping -qnc 1 192.168.1.1");

if (WIFEXITED(status)) {
    std::cout << "ping exited with exit code " << WEXITSTATUS(status) << std::endl;
}
else if (WIFSIGNALED(status)) {
    std::cerr << "ping killed by signal " << WTERMSIG(status) << std::endl;
    exit(1);
}
else {
    std::cerr << "ping exited for some other reason" << std::endl;
}

答案 1 :(得分:2)

POSIX.1-2017指出system()的调用“不是线程安全的”。

通常来说,在多线程环境中调用system()不是一个好主意。该功能的目的就像“运行辅助进程并等待其完成”。这就是为什么信号被捕获和阻塞的原因。

如果您希望您的主进程被某种方式杀死(例如,通过按Ctrl + C组合键),那么您可能更愿意使用popen()

答案 2 :(得分:0)

最后,只要您明确放弃命令输出(popen)或在cmd > /dev/null之前读取输出,pclose就可以正常工作,但是我最终还是选择了boost::process::system()使用execve并且不捕获SIGINT的情况:

bool ping(const std::string& ip,
          uint32_t count = 1,
          std::chrono::seconds timeout = 1s)
(
    return (0 ==
    bp::system(bp::exe = "/bin/ping",
               bp::args = { "-q", 
                            "-w", std::to_string(timeout.count()),
                            "-c", std::to_string(count),
                            ip },
               bp::std_out > bp::null));
}

popen的唯一“优势”是 ctrl + c 也会像系统一样向孩子发出信号,但不会捕获信号。就我而言,我实际上是在等待孩子正常完成。