【问题标题】:Does using sigwait and signalfd concurrently in a multithreaded program result in a race condition?在多线程程序中同时使用 sigwait 和 signalfd 会导致竞争条件吗?
【发布时间】:2022-01-20 01:36:26
【问题描述】:

我正在编写一个多线程程序,其中除其他外,我有一个线程侦听套接字以获取传入的网络连接。为了允许中断,我将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 调用返回,sigval 由处理程序线程设置。但是,我的理解是sigwait 会消耗信号,而signalfd 不会。因此,如果在signalfd 收到信号通知之前以某种方式调用了sigwait,则该程序可能会永远挂起(轮询等待未到来的信号)。我假设因为我无法让程序挂起,所以引擎盖下有一些东西可以防止这种情况发生,但我能保证这永远是真的吗?

【问题讨论】:

    标签: c++ multithreading signals race-condition


    【解决方案1】:

    我查看了 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 收到信号通知之前使用该信号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      • 2016-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      相关资源
      最近更新 更多