【发布时间】:2017-09-04 19:01:35
【问题描述】:
我目前正在研究网络编程的概念,其中我遇到了解决 select 问题的函数 pselect() 之一。使用 select() 时,可能会出现问题,即在测试 intr_flag 和调用 select 之间,如果信号发生,如果 select 永远阻塞,它将丢失。
if (intr_flag)
handle_intr(); /* handle the signal */
if ( (nready = select( ... )) < 0) {
if (errno == EINTR) {
if (intr_flag)
handle_intr();
}
但是,它说使用 pselect,我们现在可以将这个示例可靠地编码为
sigset_t newmask, oldmask, zeromask;
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
sigprocmask(SIG_BLOCK, &newmask, &oldmask); /* block SIGINT */
if (intr_flag) //here
handle_intr(); /* handle the signal */
if ( (nready = pselect ( ... , &zeromask)) < 0) {
if (errno == EINTR) { //here
if (intr_flag)
handle_intr ();
}
...
}
它对代码可靠的解释是 - 在测试 intr_flag 变量之前,我们阻止了 SIGINT。当调用 pselect 时,它用一个空集(即 zeromask)替换进程的信号掩码,然后检查描述符,可能会进入睡眠状态。但是当 pselect 返回时,进程的信号掩码会重置为调用 pselect 之前的值(即阻塞 SIGINT)。
但是在上面提到的带有 pselect 的代码中,我们阻塞了信号,那么我们如何检查错误 EINTR?由于 pselect 会阻止所有信号,因此当发生中断时,它应该阻止该信号中断或传递给进程。只有当 pselect 返回时,才能传递信号。
根据前面提到的注释here前面的行,在调用 pselect 之前或在第一次检查和 pselect 之间或调用 pselect 时仍然可能发生中断信号,这与阻塞中断和任何其他信号,因此应该导致与 select 存在竞争条件。
请任何人解释这是怎么可能的,因为我是这些概念的新手。
【问题讨论】:
标签: sockets unix network-programming multiplexing