c - 如果在取消点调用信号处理程序会发生什么?

标签 c linux pthreads posix cancellation

假设应用程序在取消点被阻塞,例如 read,并且接收到信号并调用信号处理程序。 Glibc/NPTL 通过在系统调用期间启用异步取消来实现取消点,据我所知,异步取消将在信号处理程序的整个期间保持有效。这当然是非常错误的,因为有很多函数不是异步取消安全的,但需要从信号处理程序中安全调用。

这留给我两个问题:

  • 是我错了还是 glibc/NPTL 行为真的有这么危险?如果是,这种危险行为是否合规?
  • 根据 POSIX,如果在进程正在执行作为取消点的函数时调用信号处理程序,应该会发生什么情况?

编辑: 我几乎说服自己,任何作为 pthread_cancel 潜在目标的线程都必须确保作为取消点的函数永远不会从信号中调用该线程上下文中的处理程序:

一方面,任何可以在可能被取消的线程中调用并使用任何异步取消不安全函数的信号处理程序必须在调用任何取消函数之前禁用取消观点。这是因为,从被信号中断的代码的角度来看,任何此类取消都等同于异步取消。另一方面,信号处理程序不能禁用取消,除非调用信号处理程序时将运行的代码仅使用异步信号安全函数,因为pthread_setcancelstate不是异步信号安全的。

最佳答案

回答我自己问题的前半部分:glibc 确实表现出我预测的行为。在取消点阻塞时运行的信号处理程序在异步取消下运行。要查看此效果,只需创建一个调用将永远(或长时间)阻塞的取消点的线程,等待片刻,向其发送信号,再次等待片刻,然后取消并加入它。信号处理程序应该以某种方式摆弄一些 volatile 变量,使其清楚地表明它在异步终止之前运行了不可预测的时间量。

至于 POSIX 是否允许这种行为,我仍然不能 100% 确定。 POSIX 声明:

Whenever a thread has cancelability enabled and a cancellation request has been made with that thread as the target, and the thread then calls any function that is a cancellation point (such as pthread_testcancel() or read()), the cancellation request shall be acted upon before the function returns. If a thread has cancelability enabled and a cancellation request is made with the thread as a target while the thread is suspended at a cancellation point, the thread shall be awakened and the cancellation request shall be acted upon. It is unspecified whether the cancellation request is acted upon or whether the cancellation request remains pending and the thread resumes normal execution if:

  • The thread is suspended at a cancellation point and the event for which it is waiting occurs

  • A specified timeout expired

before the cancellation request is acted upon.

大概执行信号处理程序不是“暂停”的情况,所以我倾向于将 glibc 的行为解释为不符合规范。

关于c - 如果在取消点调用信号处理程序会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5408303/

相关文章:

调用的对象类型 'int' 不是 xcode 中的函数或函数指针

php - IBM-DB2 在 Linux 系统上的 xampp1.7.1 上安装失败

python - 获取 Unix/Linux 远程主机支持的文件/目录信息的最佳方法是什么

linux - Qt 找不到库

c - C 中 POSIX 线程的并行 I/O

c - 二维数组动态分配中的段错误

c - SDL_GL_Extensions 支持总是返回 SDL_False

c - 访问未定义的外部数组

c - 我无法让该线程正确显示其 ID

c++ - pthread_create(),如何从传递的函数中获取返回值