【发布时间】:2012-01-01 14:51:35
【问题描述】:
在 fork 调用之后,我有一个父亲必须将 sigusr1 或 sigusr2(基于“cod”变量的值)发送给他的孩子。孩子必须在收到 sigusr1 或 sigusr2 之前安装适当的处理程序。为此,我暂停了父亲,等待孩子向他发出信号,告诉他他已完成处理程序的安装。父亲由 sigusr1 发出信号,并且该信号的处理程序在 fork 调用之前安装。但是,似乎父亲无法从暂停中返回,这让我认为他实际上从未调用过 sigusr1 处理程序。
[...]
typedef enum{FALSE, TRUE} boolean;
boolean sigusr1setted = FALSE;
boolean sigusr2setted = FALSE;
void
sigusr1_handler0(int signo){
return;
}
void
sigusr1_handler(int signo){
sigusr1setted = TRUE;
}
void
sigusr2_handler(int signo){
sigusr2setted = TRUE;
}
int main(int argc, char *argv[]){
[...]
if(signal(SIGUSR1, sigusr1_handler0) == SIG_ERR){
perror("signal 0 error");
exit(EXIT_FAILURE);
}
pid = fork();
if (pid == 0){
if(signal(SIGUSR1, sigusr1_handler) == SIG_ERR){
perror("signal 1 error");
exit(EXIT_FAILURE);
}
if(signal(SIGUSR2, sigusr2_handler) == SIG_ERR){
perror("signal 2 error");
exit(EXIT_FAILURE);
}
kill(SIGUSR1, getppid()); // wake up parent by signaling him with sigusr1
// Wait for the parent to send the signals...
pause();
if(sigusr1setted){
if(execl("Prog1", "Prog1", (char*)0) < 0){
perror("exec P1 error");
exit(EXIT_FAILURE);
}
}
if(sigusr2setted){
if(execl("Prog2", "Prog2", (char*)0) < 0){
perror("exec P2 error");
exit(EXIT_FAILURE);
}
}
// Should'nt reach this point : something went wrong...
exit(EXIT_FAILURE);
}else if (pid > 0){
// The father must wake only after the child has done with the handlers installation
pause();
// Never reaches this point ...
if (cod == 1)
kill(SIGUSR1, pid);
else
kill(SIGUSR2, pid);
// Wait for the child to complete..
if(wait(NULL) == -1){
perror("wait 2 error");
exit(EXIT_FAILURE);
}
[...]
}else{
perror("fork 2 error");
exit(EXIT_FAILURE);
}
[...]
exit(EXIT_SUCCESS);
}
【问题讨论】:
-
我怀疑您已经产生了与您预期相反的竞争条件。子进程在父进程到达
pause之前向父进程发送了SIGUSR1。 -
多放一些 printf()(并确保你刷新),这样你就可以看到孩子走了多远,以及是否调用了父母的信号处理程序。这会告诉你更多。
-
@OliCharlesworth:没看到……谢谢。
-
信号处理程序和非处理程序代码(您的
booleanobjects)之间共享的对象必须具有volatile sig_atomic_t类型,否则代码未定义。 -
顺便说一下,没有必要测试任何
exec*()系列函数的返回值。如果系统调用返回,则失败。