处理由于exception而展开的C ++析构函数中的pthread取消点

我试图实施一个范围守卫类,并遇到了Linux上取消点的问题。 从我发现的情况来看,Linux在exception情况下实现了pthread取消,其中exception不能在用户的catch块中处理(即必须重新抛出)。 这导致下面的示波器防护实现的问题,试图忽略其相关函数可能抛出的任何exception:

#include <pthread.h> #include <stdio.h> #include <unistd.h> #include <functional> struct scope_guard { template <typename T> scope_guard(T func) : function_(func) {} ~scope_guard() { try { function_(); } catch (...) {} } std::function<void()> function_; }; extern "C" { void* thread_func(void*) { try { scope_guard guard( [](void) { // wait for a cancellation event while (true) { pthread_testcancel(); } }); throw int(); } catch (int&) {} return 0; } } int main(void) { pthread_t thread; int ret; if (0 != (ret = pthread_create(&thread, NULL, &thread_func, NULL))) { fprintf(stderr, "pthread_create failed: %d\n", ret); return 1; } sleep(1); if (0 != (ret = pthread_cancel(thread))) { fprintf(stderr, "pthread_cancel failed: %d\n", ret); return 1; } void* thread_ret; if (0 != (ret = pthread_join(thread, &thread_ret))) { fprintf(stderr, "pthread_join failed: %d\n", ret); return 1; } return 0; } ~scope_guard() { try { function_(); } catch (abi::__forced_unwind&) { throw; } catch (...) {} } 

这在Solaris,HPUX和AIX上可以正常工作,但在Linux上会产生以下错误并中止:

 FATAL: exception not rethrown 

这是由~scope_guardcatch (...)块引起的,它捕获但不重新抛出pthread取消exception。

根据这篇文章,似乎处理这些取消exception的推荐方法是重新抛出一个catch (...)块的exception,或显式捕获并重新抛出取消exception,如下所示:

  ~scope_guard() { try { function_(); } catch (abi::__forced_unwind&) { throw; } catch (...) {} } 

然而,这两种方法都会导致从这个descructor抛出一个新的exception,导致问题终止,因为现有的exception已经在退栈。 在我的testing中,报告了以下内容:

 terminate called without an active exception 

有没有办法在Linux上处理这种情况?

~scope_guard()的第二个版本是正确的。

这里的问题是,为什么在thread_func() throw int() thread_func() ? 删除它,你的代码将正常工作。

如果你真的想扔int,你应该需要写如下:

 void* thread_func(void*) { scope_guard guard( [](void) { // wait for a cancellation event while (true) { pthread_testcancel(); throw int(); // Throw either here } throw int(); // Or here }); return 0; } 

请注意,您应该将所有“可能的投掷代码”放在scope_guard的函数中。