在多线程程序中同时使用 sigwait 和 signalfd 会导致竞争条件吗?

Does using sigwait and signalfd concurrently in a multithreaded program result in a race condition?

我正在编写一个多线程程序,其中有一个线程监听传入网络连接的套接字。为了允许中断,我将 pollsignalfd 结合使用(而不是原始的 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 不会。因此,如果 sigwaitsignalfd 收到信号通知之前以某种方式被调用,则该程序可能会永远挂起(轮询等待未到来的信号)。我假设因为我无法设法让程序挂起,所以引擎盖下有一些东西可以防止这种情况发生,但我能保证这永远是真的吗?

我查看了 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 收到有关信号的通知之前消耗信号。