I believe you have misunderstood slightly how exec
modifies signal dispositions. In the Linux exec
man page, for example(1), it states that (my emphasis):
所有进程属性都会在execve()
,但以下情况除外:
被捕获的信号是not与被忽略的信号相同,如signal
手册页:
使用这些系统调用,进程可以选择在传递信号时发生以下行为之一:
- 执行默认操作;
-
ignore信号;或者
-
catch带有信号处理程序的信号,信号处理程序是程序员定义的函数,在传递信号时自动调用。
这实际上是有道理的,因为虽然忽略信号可以通过exec
调用,信号处理程序不能 - 用于处理信号的函数已被替换exec
调用,因此尝试调用它很可能是灾难性的。
您可以通过编译以下两个程序来看到继承“忽略”配置的这种行为,qqp.c
:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
int main (void) {
signal (SIGINT, SIG_IGN);
puts("Parent start");
if (fork() == 0)
execl ("./qqc", 0);
wait(0);
sleep (1);
puts("Parent end");
return 0;
}
and qqc.c
:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int main (void) {
//signal (SIGINT, SIG_DFL);
puts("Child start");
sleep (60);
puts("Child end");
return 0;
}
请注意,您还可以更改第一个代码示例中的配置fork
和exec
。如果您实际上无法控制第二个代码示例将执行的操作(例如,如果您正在调用未编译的可执行文件),那么这将是更好的选择。
Running qqp
, neither the parent nor child will exit prematurely no matter how many times you press CTRL-C. But, uncomment out the line that reverts to default behaviour and you can break out of the child easily.
因此,如果您希望您的孩子恢复默认行为,您需要在孩子本身中执行此操作,例如:
signal (SIG_INT, SIG_DFL);
(1) POSIX has a little more detail http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html on what happens:
信号设置为默认操作(SIG_DFL
) 调用过程映像中的操作应设置为新过程映像中的默认操作。除了SIGCHLD
,设置为忽略的信号(SIG_IGN
)由调用过程映像设置为被新过程映像忽略。设置为由调用过程映像捕获的信号应设置为新过程映像中的默认操作(请参阅<signal.h>
)。如果SIGCHLD
信号被设置为被调用进程映像忽略,未指定是否SIGCHLD
信号被设置为被忽略或设置为新过程映像中的默认操作。
而且,就您的编辑而言,我提出的解决方案有效,但它给您提出了另一个问题:
这是否意味着信号和信号处理都可以通过执行命令传播?
信号本身并不通过exec
调用时,信号实际上是正在生成的“中断”。这与信号处理程序(处理信号的代码)或信号处理(信号发生时做什么)不同。如上所示,处置可能会继续存在exec
调用但处理程序不能。信号也没有。
What you're seeing when you press CTRL-C and multiple processes are affected has nothing to do with inheriting signals across the exec
boundary, it's more to do with the terminal stuff.
A signal delivered to an individual process will not affect any of its child processes. However, pressing CTRL-C does not send a signal to an individual process. The POSIX terminal interface has a concept of controlling terminals and process groups:
每个进程也是进程组的成员。每个终端设备记录一个进程组,称为其前台进程组。进程组控制终端访问和信号传递。终端生成的信号被发送到属于终端前台进程组成员的所有进程。