处理multithreading程序中的异步信号

Linux Programming Interface提到了一种在multithreading程序中处理异步信号的方法:

  • 所有线程都阻止进程可能接收的所有异步信号。 最简单的方法是在创建任何其他线程之前阻止主线程中的信号。 随后创建的每个线程都将inheritance主线程信号掩码的副本。
  • 使用sigwaitinfo()sigtimedwait()sigwait()创建一个接受传入信号的专用线程。

这种方法的优点是同步接收异步生成的信号。 由于它接受传入信号,专用线程可以安全地修改共享变量(在互斥控制下)并调用非异步安全function。 它还可以发信号通知条件变量,并且可以实现其他线程和进程通信和同步机制。

现在的问题是:

  1. 当内核想要传递信号时,它会选择任意一个进程内的线程。 从哪里可以知道将信号传递给专用线程?
  2. pthread API是非同步安全的函数。 那么我们如何在信号处理程序中使用它们?

当内核提供过程导向信号时,它会选择其中一个没有阻塞信号的线程。 这意味着它永远不会选择除信号处理线程之外的任何线程(其行为类似于在sigwaitinfo()或类似物中被阻塞时信号sigwaitinfo()阻塞)。 换句话说:内核知道在哪里传递信号,因为你已经安排了这样的事情,即信号处理线程是唯一允许传递信号的线程。

不在信号处理程序中使用pthreads API或任何非异步信号安全函数。 概述的解决方案不处理信号处理程序中的信号 – 它在sigwaitinfo()返回后处理信号处理线程的正常执行流程内的信号。 这允许它访问非异步信号安全function,这是重点。

请记住,提议是在生成任何线程或接收任何信号之前,在进程执行的早期阻止信号(使用pthread_sigmask())。

回答你的问题:

  1. 阅读sigwait() (和/或sigwaitinfo() )的手册页。 当内核想要向您的进程发送信号但是所有线程都阻塞了信号时,信号会“排队”。 它保持排队,直到(a)一些线程解锁信号; 或(b)某些线程在信号上调用sigwait()或sigwaitinfo()。 这里的提议是专门用一个线程来完成后者。

  2. 这个想法是你永远不会运行任何信号处理程序,因为没有线程可以解锁信号。 相反,一个线程用sigwait()等待信号,然后它处理信号。 这一切都发生信号处理环境之外,这是提案的美妙之处。

您可以使用其他机制从信号处理程序间接调用pthread API。 在主线程中,创建一个侦听某些命令的Unix域套接字。 信号处理程序可以使用代码连接到套接字并将命令发送到主线程以调用您希望调用的pthread API。