使用两个pause()来捕获两个信号但是失败了

时间:2013-12-23 13:15:48

标签: c linux

我正在编写一个程序,要求两个孩子做某事。这两个孩子在工作完成后向其父母发送两个不同的信号。同时,父母使用两个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()收到了两个信号。这可能吗?

1 个答案:

答案 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))同步。