我一直在研究glibc/nptl对取消点的实现,并将其与posix进行比较,除非我弄错了,否则这是完全错误的。使用的基本模型是:
int oldtype = LIBC_ASYNC_CANCEL(); /* switch to asynchronous cancellation mode */
int result = INLINE_SYSCALL(...);
LIBC_CANCEL_RESET(oldtype);
根据POSIX:
当函数调用期间暂停时,对取消请求采取行动的副作用与当对函数的调用被信号中断且给定函数返回[eintr]时,单线程程序中可能出现的副作用相同。在调用任何取消清理处理程序之前,会发生任何此类副作用。
我读这篇文章的意思是如果我打电话
open
我可以预料
任何一个
在它无法打开文件之前被取消(连同我的整个线程),
或
返回有效的文件描述符或-1和
errno
值,但决不创建新的文件描述符,然后将其丢失到void中。另一方面,取消点的glibc/nptl实现似乎允许一个竞争条件,即取消请求发生在系统调用返回之后,但发生在
LIBC_CANCEL_RESET
发生。
是我疯了,还是他们的实施真的这么失败了?如果是这样的话,POSIX是否允许这样的破坏行为(除非手动延迟,否则似乎会使取消完全不可用),或者它们只是公然忽略POSIX?
如果这个行为实际上被破坏了,那么在没有这种竞争条件的情况下实现它的正确方法是什么?