代码之家  ›  专栏  ›  技术社区  ›  R.. GitHub STOP HELPING ICE

发送进程中所有线程的信号

  •  9
  • R.. GitHub STOP HELPING ICE  · 技术社区  · 14 年前

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

    • 最初安装信号处理程序,并在所有线程中解除阻止信号。
    • 当一个线程想要发送“广播”信号时,它获取一个互斥锁并设置一个广播正在进行的全局标志。
    • 发送器阻塞信号(使用 pthread_sigmask )为自己,并进入一个循环重复调用 raise(sig) 直到 sigpending 指示信号处于挂起状态(信号被阻止时没有剩余线程)。
    • 当线程接收到该信号时,它们会对其进行操作,但在信号处理程序中等待清除广播标志,以便该信号保持屏蔽状态。
    • 发送方通过解除对信号的阻塞来完成循环(以便获得自己的传递)。
    • 当发送方处理自己的信号时,它会清除全局标志,以便所有其他线程可以继续其业务。

    我遇到的问题是 pthread_sigmask线程 不被尊重。如果我在 strace (可能是由于不同的调度时间),但是只要我单独运行它,发送者就会收到它自己的信号(尽管已经阻塞了它…?)其他线程都没有得到调度。

    有什么问题吗?我试过用 sigqueue 而不是 raise ,探测信号屏蔽,添加 sleep 到处都是,以确保线程耐心地等待他们的信号等,现在我不知所措。

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

    • 在任何给定的时间,我可以知道运行的线程数,并且如果需要的话,我可以防止所有的线程创建和退出。
    • 想要执行广播信号的线程获取一个锁(因此没有其他线程可以同时执行),然后为自己阻塞该信号,并发送 num_threads 向进程发送信号,然后为其自身解除锁定信号。
    • 信号处理程序以原子方式递增一个计数器,并且信号处理程序的每个实例都等待,直到该计数器等于 多线程 回来。
    • 进行广播的线程也等待计数器到达 多线程 ,然后释放锁。

    一个可能的问题是,如果内核内存不足,信号将不会排队(Linux似乎有这个问题)。你知道如果 信号队列 当呼叫者无法对信号进行排队时(在这种情况下,我将循环直到成功),可靠地通知呼叫者,或者信号可能会无声地丢失?

    编辑2: 它现在好像起作用了。根据文件 信号队列 ,它返回 EAGAIN 如果它无法对信号进行排队。但为了稳健性,我决定继续打电话 信号队列 直到 num_threads-1 信号处理程序正在运行,交叉调用 sched_yield 在我发出 num_线程-1 信号。

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

    4 回复  |  直到 14 年前
        1
  •  4
  •   psmears Touffy    14 年前

    raise() 将信号发送到当前线程(仅限),因此其他线程不会接收到该信号。我怀疑事实是 strace 让事情运转是个错误 斯特拉斯 (由于它的工作方式,它最终会截获发送到进程的所有信号并重新提升它们,因此它可能以错误的方式重新提升它们…)。

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

    然而,另一个潜在的问题是 sigpending() 可以指示在所有线程都接收到信号之前,该信号在进程上处于挂起状态—这意味着至少有一个这样的信号在该进程上处于挂起状态,并且还没有CPU可用于运行线程来传递它。。。

    你能详细描述一下你的目标吗?你希望它有多轻便?几乎可以肯定的是,有更好的方法可以做到这一点(信号几乎总是让人头疼的,尤其是与线程混合时…)

        2
  •  2
  •   blaze    14 年前

    在多线程程序中,raise(sig)等同于pthread_kill(pthread_self(),sig)。 尝试杀死(getpid(),sig)

        3
  •  0
  •   caf    14 年前

    考虑到您显然可以锁定线程的创建和销毁,您是否可以让“广播”线程将所需的更新发布到每个线程队列中的线程本地状态,每个线程在使用线程本地状态时都会对其进行检查?如果有未完成的更新,则首先应用它们。

        4
  •  0
  •   spfendtner    10 年前

    您正在尝试同步一组线程。 从设计模式的角度来看,问题的pthread本机解决方案是pthread屏障。