如果在取消点上调用信号处理程序,会发生什么情况?

| 假设在取消点(例如“ 0”)处阻止了应用程序,并且接收到信号并调用了信号处理程序。 Glibc / NPTL通过在系统调用期间启用异步取消来实现取消点,据我所知,异步取消将在信号处理程序的整个期间保持有效。当然,这将是完全错误的,因为有许多函数不是异步取消安全的,但是从信号处理程序调用时必须安全。 这给我留下了两个问题: 我是错了吗,还是glibc / NPTL行为确实被危险地破坏了?如果是这样,那么这种危险行为是否合规? 根据POSIX,如果在进程执行作为取消点的函数的过程中调用信号处理程序,应该发生什么? 编辑:我几乎已经说服自己,任何可能是ѭ1的目标的线程都必须确保在该线程的上下文中永远不能从信号处理程序中调用取消点的函数: 一方面,可以在可能被取消的线程中调用并且使用任何异步取消不安全函数的任何信号处理程序必须在调用任何作为取消点的函数之前禁用取消。这是因为,从信号中断的代码的角度来看,任何这种取消都将等同于异步取消。另一方面,信号处理程序不能禁用取消,除非调用信号处理程序时将运行的代码仅使用异步信号安全功能,因为
pthread_setcancelstate
不是异步信号安全功能。     
已邀请:
要回答我自己的问题的前半部分:glibc确实表现出了我所预测的行为。在取消点被阻塞时运行的信号处理程序在异步取消下运行。要看到这种效果,只需创建一个线程,该线程调用一个将永久(或长时间)阻塞的取消点,请稍等片刻,向其发送信号,再等待片刻,然后取消并加入它。信号处理程序应该以某种易变的变量来摆弄,以使其清楚地知道在异步终止之前,它运行了不可预测的时间。 至于POSIX是否允许这种行为,我仍然不确定100%。 POSIX指出:   每当线程启用取消功能并且以该线程为目标发出取消请求,然后该线程调用任何作为取消点的函数(例如pthread_testcancel()或read())时,应执行取消请求在函数返回之前。如果一个线程启用了取消功能,并且在线程被挂起在取消点的同时以该线程为目标发出了取消请求,则应唤醒该线程并执行取消请求。在以下情况下,不确定是否执行取消请求或取消请求是否仍处于挂起状态,并且线程恢复正常执行:         线程在取消点处挂起,并且正在等待该事件   指定的超时时间已过期         在取消请求生效之前。 假定执行信号处理程序不是“挂起”的情况,因此我倾向于将glibc的行为解释为不符合要求。     
丰富, 我在进行Alex Oliva为glibc进行的AC安全文档审查时遇到了这个问题。 我认为GNU C库实现(基于nptl)没有中断。虽然确实可以在阻止系统调用(必须是取消点)周围启用异步取消,但这种行为仍应保持一致。 的确,启用异步取消后获取的信号将导致运行了异步取消的信号处理程序运行。确实,在该处理程序中执行也不是异步取消安全的任何操作都是危险的。 的确,如果另一个线程以信号运行线程为目标调用pthread_cancel,则将立即采取这种取消措施。这仍然与POSIX的措辞“在函数返回之前”(在这种情况下,未返回读取并且目标线程在信号处理程序中)一起使用。 信号的问题在于,它导致线程处于两个同时状态,两个状态都永久处于取消点并正在执行指令。如果取消请求到达,我认为立即采取行动是一致的。尽管奥斯汀集团可能会澄清。 glibc实现的问题在于,它需要由待取消线程执行的所有信号处理程序。只调用异步取消安全函数。这是一项非显而易见的要求,并非源自标准,但不会使其不符合标准。 解决信号处理程序脆弱性的潜在解决方案: 不要启用异步取消来阻止系统调用,而应在取消实现中启用新的IN_SYSCALL位。 当调用pthread_cancel且目标线程已设置IN_SYSCALL时,则像通常对异步取消操作一样将SIGCANCEL发送到该线程,但是SIGCANCEL处理程序不执行任何操作(除了中断syscall的副作用)。 围绕系统调用的包装器将查找已发送的取消,并在包装​​器返回之前取消线程。 尽管将此内容发布到堆栈上很有趣,但我不知道其他人会读到此内容,并且可以详细地回答您的问题。 我认为,任何进一步的讨论都应该在POSIX标准讨论的一部分中在Austin Group邮件列表上进行,或者应该在glibc实现讨论的一部分上在libc-alpha上进行。     
我认为您正在寻找的是两件事的结合: 某些系统调用可能会被信号中断,从而导致返回“ 3”错误。这是正常现象,但是例如,如果您处于“ 0”中间,那么从流中什么也没读,我还不清楚如何发生?也许有人可以对此发表评论以帮助澄清。 像您担心的那些那样,不应中断的系统调用应包装在对in5 to(或线程中的
pthread_sigmask
)的调用中,以防止它们被中断。重新启用信号后,在阻塞状态下接收到的所有信号都将被传送。但是,与中断一样,如果阻塞时间太长,则可能由于覆盖而错过一些中断(多次接收到相同信号视为一个待处理信号)。     

要回复问题请先登录注册