http://udrepper.livejournal.com/21541.html

Ulrichがpthread_cancel()とC++は混ぜるなキケンになってるけど、オレは正しいんだ正しいんだ正しいんだ。
という趣旨のブログを書いております。

以下いつものように(主に笑いをとるための)超訳。正確な情報が欲しい人は元URLを読んでくださいませ。



#include <cstdlib>
#include <iostream>
#include <pthread.h>

static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;

static void *tf (void *)
{
try {
::pthread_mutex_lock(&m);
::pthread_cond_wait (&c, &m);
} catch (...) {
// do something
}
}

int main ()
{
pthread_t th;
::pthread_create (&th, NULL, tf, NULL);
// do some work; simulate using sleep
std::cout << "Wait a bit" << std::endl;
sleep (1);
// cancel the child thread
::pthread_cancel (th);
// wait for it
::pthread_join (th, NULL);
}


pthread_cacnel()は内部実装にC++例外を使ってる。だから、このようなコードは
tf() で pthread_cond_wait() から上がってきた秘密のglibc専用例外をキャッチしてしまい、
かつ、例外のrethowをしていないので、C++界の重罪、rethrow忘れの罪によりプロセスは
abortしてしまう


$ ./test
Wait a bit
FATAL: exception not rethrown
Aborted (core dumped)



正しい直し方は gcc specialな <cxxabi.h> をインクルードして、同じくスペシャルな
abi::__forced_unwind& をrethrowすることだよ。以下のように


@@ -1,6 +1,7 @@
#include
#include
#include
+#include

static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
@@ -11,6 +12,8 @@
try {
::pthread_mutex_lock(&m);
::pthread_cond_wait (&c, &m);
+ } catch (abi::__forced_unwind&) {
+ throw;
} catch (...) {
// do something
}


cxxabi.h はたしかgcc 4.3以降で提供されてるはず。
まあ、こんなの以下のマクロで一発解決できるんだから問題のうちにも入らないよ

#define CATCHALL catch (abi::__forced_unwind&) { throw; } catch (...)

だから、オレは直さなくていいよね。

オレは正しいんだ正しいんだ正しいんだ。