如何解决多线程中断系统调用
我有一堆 pthread,每个线程都阻塞在系统调用上,例如 recv()
和 wait()
。
我想在信号到达时中断它们(并使它们返回 errno = EINTR
),所以我使用 sigaction()
而不使用 SA_RESTART
来设置中断处理程序。最终目标是优雅地退出整个程序。
然而,似乎只有处理信号的线程被中断,而其他线程继续阻塞它们的系统调用。
我如何打断他们?
解决方法
signal(7)-s 与 pthreads(7) 不友好(在 Linux 上使用 clone(2) 实现)
考虑(像 Qt 那样)在每个线程中都有一些事件循环,并使用 signalfd(2)。它与 poll(2) 兼容,因此与 socket(7) 兼容。
或者,在您的信号处理程序中设置一些全局 volatile sigatomic_t flag;
,并在每个线程中测试该标志。另见<stdatomic.h>
注意 continuation passing style 范式。
,为了中断所有线程,您需要使用 pthread_kill
分别向它们发送信号,而不是向进程发送信号,这意味着您需要保留可能想要发送信号的线程列表。请注意,由于信号总是有可能在阻塞系统调用之前的最后一次检查之后到达,但在系统调用实际进行之前,总是有必要重复信号(使用适当的退避)直到发出信号的线程以某种方式响应以指示它已经接受了中断请求。这是信号中断的原始概念中固有的竞争条件,即使没有线程也是如此。
如果您的意图是线程在中断它们阻塞的系统调用后不久终止,您可以使用线程取消而不是信号。这不需要处理 EINTR
的问题(上述竞争条件等),但需要围绕取消的可能性来构建代码。这意味着根据正在执行的代码是否准备好处理它来启用/禁用取消,并设置取消处理程序以适当地退出任何不一致的状态、释放资源、释放锁等。
如果您确实使用了信号,则 volatile sigatomic_t
对象不应在解决方案中发挥任何作用。信号处理程序可以而且应该是一个完全空的函数;它的唯一目的是导致EINTR
。信号线程和信号线程应通过标准 pthread 同步原语(互斥体、可能的条件变量和/或信号量)进行通信,以指示中止操作的请求并确认对请求的操作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。