在多线程程序中同时使用 sigwait 和 signalfd 会导致竞争条件吗?
Does using sigwait and signalfd concurrently in a multithreaded program result in a race condition?
我正在编写一个多线程程序,其中有一个线程监听传入网络连接的套接字。为了允许中断,我将 poll
与 signalfd
结合使用(而不是原始的 await
调用)。但是,我还有其他线程需要能够通知潜在的中断,因此我在专用线程中使用 sigwait
调用来等待信号。我试图让比赛发生在下面的代码中:
int main()
{
int sigval = 0;
sigset_t mask;
sigemptyset (&mask);
sigaddset (&mask, SIGINT);
pthread_sigmask(SIG_BLOCK, &mask, nullptr);
int sfd = signalfd(-1, &mask, SFD_NONBLOCK);
auto handler = std::thread([&] {
int signal;
sigwait(&mask, &signal);
sigval = signal;
});
pollfd pfd[1] = {{.fd=sfd, .events=POLLIN}};
int ret = poll(pfd, 1, -1);
std::cout << "Poll returned with revents = " << pfd[0].revents << std::endl;
handler.join();
std::cout << "Handled thread set sigval to: " << sigval << std::endl;
return 0;
}
每次我 运行 这个并用 SIGINT
杀死它时,它似乎工作,因为 poll
调用 returns,并且 sigval
由处理程序线程设置。但是,我的理解是 sigwait
会消耗信号,而 signalfd
不会。因此,如果 sigwait
在 signalfd
收到信号通知之前以某种方式被调用,则该程序可能会永远挂起(轮询等待未到来的信号)。我假设因为我无法设法让程序挂起,所以引擎盖下有一些东西可以防止这种情况发生,但我能保证这永远是真的吗?
我查看了 linux 源代码,并得出了我自己的问题的答案:没有竞争条件,因为 signalfd 观察者在 之前被明确通知 信号被发送,所以他们总是会在信号被发送(和捕获)之前得到通知。具体来说,在 linux/kernel/signal.c
中,我们看到:
out_set:
signalfd_notify(t, sig); // <-- signalfd notified
sigaddset(&pending->signal, sig);
...
complete_signal(sig, t, type); // <-- sends the signal
因此 sigwait
不可能在 signalfd
收到有关信号的通知之前消耗信号。
我正在编写一个多线程程序,其中有一个线程监听传入网络连接的套接字。为了允许中断,我将 poll
与 signalfd
结合使用(而不是原始的 await
调用)。但是,我还有其他线程需要能够通知潜在的中断,因此我在专用线程中使用 sigwait
调用来等待信号。我试图让比赛发生在下面的代码中:
int main()
{
int sigval = 0;
sigset_t mask;
sigemptyset (&mask);
sigaddset (&mask, SIGINT);
pthread_sigmask(SIG_BLOCK, &mask, nullptr);
int sfd = signalfd(-1, &mask, SFD_NONBLOCK);
auto handler = std::thread([&] {
int signal;
sigwait(&mask, &signal);
sigval = signal;
});
pollfd pfd[1] = {{.fd=sfd, .events=POLLIN}};
int ret = poll(pfd, 1, -1);
std::cout << "Poll returned with revents = " << pfd[0].revents << std::endl;
handler.join();
std::cout << "Handled thread set sigval to: " << sigval << std::endl;
return 0;
}
每次我 运行 这个并用 SIGINT
杀死它时,它似乎工作,因为 poll
调用 returns,并且 sigval
由处理程序线程设置。但是,我的理解是 sigwait
会消耗信号,而 signalfd
不会。因此,如果 sigwait
在 signalfd
收到信号通知之前以某种方式被调用,则该程序可能会永远挂起(轮询等待未到来的信号)。我假设因为我无法设法让程序挂起,所以引擎盖下有一些东西可以防止这种情况发生,但我能保证这永远是真的吗?
我查看了 linux 源代码,并得出了我自己的问题的答案:没有竞争条件,因为 signalfd 观察者在 之前被明确通知 信号被发送,所以他们总是会在信号被发送(和捕获)之前得到通知。具体来说,在 linux/kernel/signal.c
中,我们看到:
out_set:
signalfd_notify(t, sig); // <-- signalfd notified
sigaddset(&pending->signal, sig);
...
complete_signal(sig, t, type); // <-- sends the signal
因此 sigwait
不可能在 signalfd
收到有关信号的通知之前消耗信号。