在不保留当前线程列表的情况下,我试图看到实时信号被传递到我进程中的所有线程。我的想法就是这样:
pthread_sigmask
),并重复调用raise(sig)
进入循环,直到sigpending
表示信号处于待处理状态(没有剩余的线程与信号受阻)。我遇到的问题是pthread_sigmask
没有受到尊重。如果我在strace
下运行测试程序(可能是由于不同的调度时间),一切正常,但是一旦我单独运行,发送者就会收到自己的信号(尽管已经阻止了它?)并且没有其他线程的安排。
任何想法可能出错?我尝试使用sigqueue
代替raise
,探测信号掩码,在整个地方添加sleep
以确保线程耐心地等待他们的信号等等。现在我我不知所措。
编辑:感谢psmears的回答,我想我明白了这个问题。这是一个潜在的解决方案。反馈会很棒:
num_threads
信号,然后解除阻塞信号为自己。num_threads
才能返回。num_threads
,然后释放锁定。一个可能的问题是,如果内核内存不足,信号将不会排队(Linux似乎有这个问题)。你知道sigqueue
是否可以在呼叫者无法排队信号时可靠地通知呼叫者(在这种情况下我会循环直到它成功),或者信号可能会无声地丢失?
编辑2:现在似乎正在运作。根据{{1}}的文档,如果它无法对信号进行排队,则返回sigqueue
。但为了提高稳健性,我决定继续调用EAGAIN
,直到sigqueue
信号处理程序正在运行,并在发送num_threads-1
信号后将呼叫交错到sched_yield
。
在线程创建时有一个竞争条件,计算新线程,但我用一个奇怪的(ab)使用读写锁解决了它。线程创建是“读取”,广播信号是“正在写入”,所以除非有线程试图广播,否则它不会在创建线程时产生任何争用。
答案 0 :(得分:4)
raise()
将信号发送到当前线程(仅),因此其他线程将不会接收它。我怀疑strace
使事情有效的事实是strace
中的一个错误(由于它的工作方式,它最终拦截发送到进程的所有信号并重新提升它们,所以它可能是以错误的方式重新提升它们......)。
您可以使用kill(getpid(), <signal>)
将信号整体发送到当前进程。
然而,您可能会看到的另一个潜在问题是sigpending()
可以在所有线程收到信号之前指示信号在进程中处于待处理状态 - 这意味着至少有一个这样的信号待处理进程,并没有CPU可用于运行线程来提供它......
您能描述一下您希望实现的目标的更多细节吗?你想要的便携性如何?几乎可以肯定有一种更好的方法(信号几乎总是一个令人头痛的问题,特别是当与线程混合时...)
答案 1 :(得分:2)
在多线程程序中,raise(sig)相当于pthread_kill(pthread_self(),sig)。 尝试kill(getpid(),sig)
答案 2 :(得分:0)
鉴于您可以显然锁定线程创建和销毁,您是否可以让“广播”线程在每个线程队列中发布线程本地状态所需的更新,每个线程在每次线程使用时都会检查线程本地状态?如果有未完成的更新,则首先应用它们。
答案 3 :(得分:0)
您正在尝试同步一组线程。 从设计模式的角度来看,针对您的问题的pthread本机解决方案将是一个pthread障碍。