指示进程中的所有线程

在不保留当前线程列表的情况下,我试图看到实时信号传递给我的进程中的所有线程。 我的想法是这样做:

  • 首先安装信号处理程序,并在所有线程中解除信号阻塞。
  • 当一个线程想要发送'广播'信号时,它会获取一个互斥并设置广播发生的全局标志。
  • 发送方为自己阻塞信号(使用pthread_sigmask ),并进入一个重复调用raise(sig)的循环,直到sigpending指示信号处于挂起状态(信号被阻塞时没有剩余线程)。
  • 当线程接收到信号时,它们会对其执行操作,但要等待信号处理程序中的广播标志被清除,以使信号保持被屏蔽。
  • 发件人通过解锁信号来完成循环(以便获得它自己的传送)。
  • 当发送者处理自己的信号时,它会清除全局标志,以便所有其他线程可以继续其业务。
  • 我遇到的问题是pthread_sigmask没有得到尊重。 如果我在strace下运行测试程序(大概是由于不同的调度时序),但一旦我单独运行测试程序,发送者就会收到它自己的信号(尽管屏蔽了它..?),而其他线程永远得到预定。

    任何想法可能是错误的? 我尝试过使用sigqueue来代替raise ,探测信号掩码,在所有地方添加sleep以确保线程耐心地等待他们的信号,等等,现在我不知所措。

    编辑:感谢psmears的回答,我想我明白了这个问题。 这是一个潜在的解决方案。 反馈会很好:

  • 在任何时候,我都可以知道正在运行的线程数量,如果需要,我可以在广播信号期间阻止所有线程的创建和退出。
  • 想要做广播信号的线程获取一个锁(所以没有其他线程可以同时进行),然后为自己阻塞信号,并向该进程发送num_threads信号,然后解除阻塞自身的信号。
  • 信号处理程序以原子方式递增计数器,并且信号处理程序的每个实例都会等待,直到该计数器等于num_threads返回。
  • 执行广播的线程也等待计数器到达num_threads ,然后释放该锁。
  • 一个可能的问题是,如果内核内存不足,信号不会排队(Linux似乎有这个问题)。 你知道sigqueue可靠地通知调用者何时无法对信号进行排队(在这种情况下,我会循环直到成功),或者信号可能会悄无声息地丢失?

    编辑2:它现在似乎在工作。 根据sigqueue的文档,如果它无法排队信号,它会返回EAGAIN 。 但为了健壮性,我决定继续调用sigqueue直到num_threads-1信号处理程序正在运行, sched_yield在发送num_threads-1信号后将调用交织到sched_yield

    线程创建时有一个竞争条件,计算新线程,但我用一个奇怪的(ab)使用读写锁来解决它。 线程创建是“读取”,广播信号是“写入”,所以除非线程试图广播,否则它不会在线程创建时产生任何争用。


    raise()将信号发送给当前线程(仅),所以其他线程不会收到它。 我怀疑,事实strace使事情的工作是在一个错误strace (因为它的工作原理它结束了拦截发送到进程和所有信号再次提高他们的方式,所以它可能是在错误的方式重新认识他们...)。

    你可以使用kill(getpid(), <signal>)将信号发送到当前进程作为一个整体。

    但是,您可能会看到另一个潜在的问题,即sigpending()可能表示信号在所有线程接收到该信号之前处于挂起状态 - 这意味着该进程至少有一个此类信号待处理,并且没有CPU已经可以运行一个线程来传递它...

    你能描述一下你打算实现的更多细节吗? 你想要它是多么便携? 几乎肯定有更好的方法来做到这一点(信号几乎总是令人头疼的事情,尤其是当与线程混合在一起时......)


    在多线程程序中,raise(sig)相当于pthread_kill(pthread_self(),sig)。 试试kill(getpid(),sig)


    考虑到你可以明显地锁定线程的创建和销毁,你可不只是让“广播”线程在每线程队列中发布所需的更新到线程本地状态,每当线程去使用线程时,本地状态? 如果有未完成的更新,则首先应用它们。

    链接地址: http://www.djcxy.com/p/50019.html

    上一篇: Signalling all threads in a process

    下一篇: How does a process come to know that it has received a signal