我一直在研究 glibc/nptl 取消点的实现,并将其与 POSIX 进行比较,除非我弄错了,否则它是完全错误的。使用的基本模型是:
int oldtype = LIBC_ASYNC_CANCEL(); /* switch to asynchronous cancellation mode */
int result = INLINE_SYSCALL(...);
LIBC_CANCEL_RESET(oldtype);
根据 POSIX:
在函数调用期间挂起时根据取消请求采取行动的副作用与单线程程序中当函数调用被信号和给定中断时可能出现的副作用相同。函数返回[EINTR]。任何此类副作用都会在调用任何取消清理处理程序之前发生。
我对这段话的解读是,如果我打电话open
,我可以期待either在无法打开文件之前被取消(以及我的整个线程),or返回有效的文件描述符或 -1 和errno
值,但永远不要创建一个新的文件描述符然后将其丢失。另一方面,取消点的 glibc/nptl 实现似乎允许竞争条件,其中取消请求发生在系统调用返回之后但之前LIBC_CANCEL_RESET
发生。
我是疯了,还是他们的实施真的这么糟糕?如果是这样,POSIX 是否允许这种破坏行为(这似乎使取消完全无法使用,除非您手动推迟),或者他们只是公然忽略 POSIX?
如果这种行为实际上被破坏了,那么在没有这种竞争条件的情况下实现它的正确方法是什么?
标准的下一段不是澄清了这一点吗:
但是,如果线程挂起于
取消点和事件
它正在等待发生在
取消请求被执行,它
未指定是否
取消请求已采取行动或
是否取消请求
保持挂起状态并且线程恢复
正常执行。
这意味着这种竞争条件是完全合法的行为。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)