R..*_*R.. 10 c linux posix pthreads cancellation
例如read
,假设应用程序在取消点被阻止,并且接收到信号并调用信号处理程序.Glibc/NPTL通过在系统调用期间启用异步取消来实现取消点,因此据我所知,异步取消将在信号处理程序的整个持续时间内保持有效.这当然是非常错误的,因为有很多函数不是异步取消安全的,但是要求从信号处理程序调用是安全的.
这让我有两个问题:
编辑:我几乎确信自己,任何潜在目标的线程pthread_cancel
必须确保永远不能从该线程的上下文中的信号处理程序调用取消点的函数:
一方面,任何可以在可能被取消并且使用任何async-cancel-unsafe函数的线程中调用的信号处理程序必须在调用任何取消点的函数之前禁用取消.这是因为,从信号中断的代码的角度来看,任何这种取消都等同于异步取消.另一方面,信号处理程序无法禁用取消,除非在调用信号处理程序时将运行的代码仅使用异步信号安全函数,因为pthread_setcancelstate
它不是异步信号安全的.
回答我自己的问题的前半部分:glibc 确实表现出了我预测的行为。在取消点阻塞时运行的信号处理程序在异步取消下运行。要看到这种效果,只需创建一个调用取消点的线程,该取消点将永远(或长时间)阻塞,等待片刻,向其发送信号,再次等待片刻,然后取消并加入它。信号处理程序应该以某种方式摆弄一些易失性变量,以明确它在异步终止之前运行了不可预测的时间。
至于 POSIX 是否允许这种行为,我仍然不能 100% 确定。POSIX 规定:
每当线程启用了可取消性并且以该线程为目标发出取消请求,然后该线程调用任何作为取消点的函数(例如 pthread_testcancel() 或 read())时,应执行取消请求在函数返回之前。如果线程启用了可取消性,并且在线程挂起于取消点时以该线程为目标发出取消请求,则应唤醒该线程并对取消请求采取行动。在以下情况下,未指定是否对取消请求采取行动,或者取消请求是否保持挂起状态并且线程恢复正常执行:
线程在取消点挂起,并且它正在等待的事件发生
指定的超时时间已过
在对取消请求采取行动之前。
据推测,执行信号处理程序并不是“暂停”的情况,因此我倾向于将 glibc 的行为解释为不符合规范。