调用系统(3)时忽略了SIGINT

SIGINT ignored while calling system(3)

本文关键字:SIGINT 系统 调用      更新时间:2023-10-16

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

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

为什么会这样,我该怎么做才能用CTRL+C退出我的进程?

您的进程阻止了这些信号,因此当用户按下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;
}

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

一般来说,在多线程环境中调用system()不是一个好主意。该函数的目的类似于"运行辅助进程并等待它完成"。这就是信号被捕获和阻断的原因。

如果您希望您的主进程以某种方式被终止(例如按Ctrl+C(,那么您可能更喜欢使用popen()

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

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也会像系统一样向孩子发出信号,但不会捕获信号。在我的情况下,我实际上想等待孩子正常完成。