是否有任何关于指定C ++异常和pthread取消的交互的动作?

时间:2012-02-25 00:43:52

标签: c++ c pthreads posix cancellation

GNU C库最近使用DWARF2展开来进行pthread取消,因此C ++异常和pthread取消清理处理程序都会通过公共调用框架展开进程调用,该过程在必要时调用自动对象的析构函数。但是,据我所知,仍然没有标准指定(POSIX)线程和C ++之间的交互,并且可能希望可移植的应用程序应该假设从取消清除上下文中抛出异常与调用{一样未定义{1}}中的{1}},以及取消具有非平凡析构函数的实时自动对象的线程也是未定义的行为。

是否有任何正在进行的标准化过程可以解决这种相互作用,或者是否可以预期未来的未定义? C ++ 11在其线程支持中是否对POSIX线程取消有任何类似的概念?

1 个答案:

答案 0 :(得分:13)

作为ISO / IEC SC22的成员,包括WG14(C),WG15(POSIX)和WG21(C ++),我可以告诉你快速答案是否定的,C ++异常和线程取消不会看到任何时候都很快。 C11和C ++ 11没有提到线程取消,并且在大约十年的时间内,在下一个主要标准发布之前,并非极不可能认识到它。

更长的答案归结为标准如何运作。基本上ISO只能标准化每个人都可以达成一致意见,人们不同意线程取消。在每个可取消的系统调用之前必须转储状态的执行线程的整个想法违背了现代软件开发的整个精神。它会导致编译器优化的巨大问题,因为与C ++异常抛出不同,线程取消被定义为与调用thread_terminate(self)相同,后者明确排除了执行任何其他操作(甚至取消处理程序在许多实现中都不可靠地调用),以及我不认为线程取消支持者会不同意这是一个糟糕的解决方案。

问题是唯一合适的替代方案是使用异步完成变体重新发布POSIX i / o API。而问题在于,不同的POSIX实现非常不同地认为异步完成。我的意思是,我们甚至不能就内核等待队列的标准达成一致,所以在实现这一目标之前,异步i / o API还有很长的路要走。我有一个建议,为下一个标准T​​C / TR的内核等待队列做一些动作,但建议的对象是故意非常简单。

我们在C11 / C ++ 11中尝试做的是使线程API始终具有非阻塞版本 - 其中只有一个API无法进行非阻塞,即thread_join( )(没有thread_timedjoin())并且我计划在获得奥斯汀工作组批准后亲自提交勘误表。在所有其他情况下,人们总是可以构建一些轮询效果不高但程序正确的东西。

从长远来看,从个人角度来说,我认为有很多理由在C语言中添加异常处理,其语义与C ++类似。你不一定会有对象支持(我实际上也支持将非虚拟对象添加到C中),但你会有堆栈解除lambda函数调用的概念。这将让我们通过正确定义的机制正式化黑客攻击。它还可以让你在编写风时编写放卷,使写入容错C变得更容易和更安全,并让旧C透明地与新C互操作。

关于在异常处理中抛出异常,我个人认为我们需要做更好的事情而不是总是自动调用terminate()。由于展开可能导致新对象的构造,或者实际上任何其他异常抛出源,我个人非常希望在终止进程之前进行所有合理的尝试来展开整个堆栈。

因此,简而言之,期望POSIX线程取消继续被视为未定义,并且从长远来看,很有可能它会被弃用以支持更好的东西。

BTW,通常POSIX线程取消在实现之​​间是非常不可移植的,因此任何使用POSIX线程取消的代码都有效地依赖于特定于平台的行为,这与使用非POSIX API相同。如果您希望代码可移植,请不要使用POSIX线程取消。而是使用select()或poll()包括魔术“请立即停止线程”文件描述符。在我自己的C ++代码中,我实际上有一个系统API包装宏,它测试这个神奇的文件描述符并抛出一个特殊的C ++异常。这可以确保所有平台上的相同行为,包括Windows。