假设应用程序在取消点被阻塞,例如read
,接收到信号并调用信号处理程序。Glibc/NPTL 通过在系统调用期间启用异步取消来实现取消点,据我所知,异步取消将在信号处理程序的整个持续时间内保持有效。这当然是非常错误的,因为有很多函数不是异步取消安全的,但需要安全地从信号处理程序调用。
这给我留下了两个问题:
- 我错了还是 glibc/NPTL 行为真的有这么危险的破坏?如果是这样,这种危险行为是否符合要求?
- 根据 POSIX,如果在进程执行作为取消点的函数时调用信号处理程序会发生什么?
编辑:我几乎说服自己,任何作为潜在目标的线程都pthread_cancel
必须确保在该线程的上下文中永远不能从信号处理程序调用作为取消点的函数:
一方面,可以在可能被取消的线程中调用的任何信号处理程序以及使用任何 async-cancel-unsafe 函数的任何信号处理程序都必须在调用作为取消点的任何函数之前禁用取消。这是因为,从被信号中断的代码的角度来看,任何这样的取消都将等同于异步取消。另一方面,信号处理程序不能禁用取消,除非在调用信号处理程序时将运行的代码仅使用异步信号安全函数,因为pthread_setcancelstate
它不是异步信号安全的。