我正在编写一个处理Linux信号的程序。更具体地说,我想在子进程中重新安装信号SIGINT,但却发现它不起作用。
以下是我的代码的简单版本:
void handler(int sig){
//do something
exit(0);
}
void handler2(int sig){
//do something
exit(0);
}
int main(){
signal(SIGINT, handler);
if ((pid = fork()) == 0) {
signal(SIGINT, handler2); // re-install signal SIGINT
// do something that takes some time
printf("In child process:\n");
execve("foo", argv, environ); // foo is a executable in local dir
exit(0);
}else{
int status;
waitpid(pid, &status, 0); // block itself waiting for child procee to exit
}
return 0;
}
当shell正在打印“在子进程中:”时,按ctrl + c。我发现函数handler
没有问题,但handler2
永远不会被执行。
你能帮我解决一下我的代码中的这个错误吗?
更新:
我希望子进程在foo
运行过程中接收SIGINT信号,这可能吗?
答案 0 :(得分:1)
这不是错误 - 调用execve
已取代正在运行的二进制映像。函数handler2()
(以及二进制的任何其他函数)不再映射到已被“foo”图像替换的程序存储器中,因此所有信号设置都将替换为默认值。
如果希望信号处理程序在“foo”运行期间处于活动状态,则必须:
这样做的一种方法是创建一个包含信号处理程序和init
函数的共享库,该函数被定义为注册所述信号处理程序的构造函数,并通过操作它来强制它进入“foo”内存。您要execve
foo(环境变量)包含
LD_PRELOAD=/path/to/shared_library.so
答案 1 :(得分:0)
@ gby的anwser给出了全面的背景知识。我在这里提供另一种没有共享库的解决方案。
每次子进程停止或终止时,父进程都将收到SIGCHLD。您可以处理此SIGCHLD信号以了解SIGINT是否终止子进程。在你的处理程序中:
pid_t pid = waitpid(pid_t pid,int * status,int options)
您可以通过waitpid函数获取子进程的状态。
if(WIFSIGNALED(status) && (pid == child_pid)){
if(WTERMSIG(status) == SIGINT){
// now you know your foo has received SIGINT.
// do whatever you like.
}
}