我正在编写一个程序,要求两个孩子做某事。这两个孩子在工作完成后向其父母发送两个不同的信号。同时,父母使用两个pause()
等待其子女。
然而,程序在第一个pause()
之后停止,并在第二个pause()
等待另一个信号。使用gdb,我发现收到了来自孩子的两个信号,但只完成了一个pause()
。
这个问题的原因是什么?
主要:
struct sigaction parent_act;
struct sigaction child_act[2];
// set the signal handlers
parent_act.sa_handler = &p0_handler;
child_act[0].sa_handler = &p1_handler;
child_act[1].sa_handler = &p2_handler;
// set the behavior when child get signal SIGUSR1 and SIGUSR2
sigaction(SIGUSR1, &child_act[0], NULL);
sigaction(SIGUSR2, &child_act[1], NULL);
// fork two child
for(i = 0; i < 2; i++){
pid[i] = fork();
// child process
else if(pid[i] == 0){
pause(); // wait for signal
return 0;
}
}
// set the behavior when parent get signal SIGUSR1 and SIGUSR2
sigaction(SIGUSR1, &parent_act, NULL);
sigaction(SIGUSR2, &parent_act, NULL);
kill(pid[0], SIGUSR1); // signal the child to do its job
kill(pid[1], SIGUSR2); // signal the other child to do its job
pause(); // wait for child
pause(); // wait for child
处理程序:
void p0_handler(int dummy)
{
return;
}
void p1_handler(int dummy)
{
// do something
kill(getppid(), SIGUSR1); // tell parent it's done
return;
}
void p2_handler(int dummy)
{
// do something
kill(getppid(), SIGUSR2); // tell parent it's done
return;
}
第一个孩子将SIGUSR1发送给父母,第二个孩子发送SIGUSR2。似乎第一个pause()
收到了两个信号。这可能吗?
答案 0 :(得分:0)
最有可能两个信号同时到达(或者第二个信号在执行信号处理程序期间到达),此时第二个pause
将无限期地等待。
问题在于,即使您喜欢设置标记“One child finished”,也无法保证在调用pause
之前其他信号不会到达。
使信号防水的唯一方法是在超时时使用select
。
int num_signals_received = 0;
void p0_handler(int dummy)
{
// signal safe action
__sync_fetch_and_add(&num_signals_received, 1);
return;
}
而不是pause
:
struct timeval timeout = {1,0}; // 1 second
while (num_signals_received < 2)
select(0, NULL, NULL, NULL, &timeout);
如果您没有设置同步信号,那么我建议您转移到共享内存(mmap/MAP_SHARED
)或基于文件描述符(pipe(2)
)同步。