pthread_cancelを試す。
はじめに
メインスレッドから生成したスレッドを途中で終了させるにはどうするのかを調査中、pthread_killが使えることがわかったが、
【POS44-C. シグナルを使用してスレッドを終了しない】
では、pthread_cancelを使用せよとあった。使ったことがないので、サンプルを作りながら、挙動を確認してみた。
それをまとめた記事である。
pthread_cancelの挙動まとめ
pthread_cancelの挙動は、大きく分けて4つある。
- キャンセルを許可/不許可 ・・・A
- 遅延取り消し/即時取り消し(非協調的) ・・・B
A×B(=2×2)の4つである。
【A】は、キャンセルされる側のスレッド上で、pthread_setcancelstate()で設定可能。
【B】は、キャンセルされる側のスレッド上で、pthread_setcanceltype()で設定可能。
キャンセル許可 | キャンセル不許可 | |
---|---|---|
遅延取り消し | 1 | 3 |
即時取り消し | 2 | 4 |
デフォルトの動作
上記表の【1】にあたる。
サンプル
デフォルトの動作がわかるサンプルを下記に示す。
andre@andre-VirtualBox:~/work/c/pthread_cancel$ cat main.c #include<stdio.h> #include<stdlib.h> #include<pthread.h> #define FIB_N 40 unsigned long fib( int n ) ★フィボナッチ数を計算 { if( n < 0 ) return 0; if( n == 0 ) return 1; if( n == 1 ) return 1; if( n > 1 ) return fib( n-1 ) + fib( n-2 ); } int thread( void* arg ) ★ cancelされる側のスレッド { int i = 0; unsigned long ret = 0; printf( "sub thread fib calc start...\n" ); for( i = 0; i < FIB_N; i++ ) { // printf( "for:%d\n", i ); ret = fib( i ); // printf( "fib(%d)=%lu\n", i, ret ); } printf( "sub thread fib calc finish!\n" ); ★ 遅延取り消しのキャンセルポイント printf( "finish thread!\n" ); ★ このメッセージは出力「されない」 return 0; } int main( void ) ★ cancelする側のスレッド { int ret = 0; pthread_t th; ret = pthread_create( &th, NULL, ( void* )thread, NULL ); printf( "main thread sleep...\n" ); sleep( 1 ); printf( "main thread wake up!\n" ); printf( "do thread cancel.\n" ); pthread_cancel( th ); ★スレッドをキャンセルする pthread_join( th, NULL ); ★ joinしないとメモリリークする。 return 0; }
実行結果
andre@andre-VirtualBox:~/work/c/pthread_cancel$ ./test_pthread_cancel main thread sleep... sub thread fib calc start... main thread wake up! do thread cancel. ★ キャンセル実行 sub thread fib calc finish! ★ キャンセルポイント
【sub thread fib calc finish!】のメッセージで、フィボナッチ数をすべて計算してから、スレッドが終了しているのがわかる。