glibcでpthread_cancelした場合、C++のデストラクタがちゃんと動く
というわけで、「キャンセルが必要ですが、pthreadのキャンセルって大変アレですよねー」、という話をしたいのだけど、もうちょっと調査が必要…具体的には、cond_waitで、mutexのアンロックとスレッドの停止をどうやってアトミックにやってるかわからない…
それはいいとして、色々見てると、glibcのpthread_cancelでは、C++のデストラクタが呼ばれるような気がした。
#include <pthread.h> #include <stdio.h> #include <unistd.h> class Die { public: ~Die() { puts("shindayo!"); } }; static void * start( void *) { Die d; pthread_mutex_t m; pthread_cond_t c; pthread_mutex_init( &m, NULL ); pthread_cond_init( &c, NULL ); pthread_cond_wait( &c, &m ); puts("kokomadekitayo!"); } int main() { pthread_t t; void *rp; int r = pthread_create( &t, NULL, start, NULL ); sleep( 1 ); pthread_cancel( t ); pthread_join( t, &rp ); }
これって規格で決められてない動作だよね…
ひょっとしたら、C++とpthread使ってて、Linux+glibcの環境依存してもいいコード書いてる時には役に立つ…かもしれない。
ちなみに、pthread_cond_waitの中身はアセンブリで書いてあるのだけど、C++例外処理を動かすために、手書きで例外テーブルが書いてあるという。
; nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S ; .section .gcc_except_table,"a",@progbits .LexceptSTART: .byte 0xff # @LPStart format (omit) .byte 0xff # @TType format (omit) .byte 0x0b # call-site format # DW_EH_PE_sdata4 .uleb128 .Lcstend-.Lcstbegin .Lcstbegin: .long .LcleanupSTART-.LSTARTCODE (....)
アホだなー。