POS41-C. スレッドの終了状態が必要ない場合は pthread_detach() または同等の関数を使用する
pthread_detach() 関数は、スレッドに割り当てられているリソースが終了時に回収可能であることをシステムに知らせるために使われる。この関数は、他のスレッドが終了状態を必要としないときに使用するべきである。
スレッドをデタッチせずに終了すると、スレッドのスタックが解放され、pthread_join() または pthread_detach() によってスレッドが破棄されるまで、ヒープや OS レベルのオブジェクトも含めすべてのリソースが残ったままになる。これらのリソースは、リソースが限られているシステムにとっては不可欠である場合があり、どの重要リソースが先に使い果たされるかにもよるが、最終的にエラーを引き起こす可能性がある。起こりやすいエラーの 1 つに、EAGAIN (Resource unavailable, try again)がある。これは、他のプロセス、スレッド、またはミューテックスの作成や初期化を行うリソースが不足したときに、fork()、pthread_create()、pthread_mutex_init() などの関数によって設定される。
違反コード
次のコード例は、正しく終了されていないスレッドプールを示している。
size_t const thread_no = 5; char mess[] = "This is a test"; void *message_print(void *ptr){ char *msg; msg = (char *) ptr; printf("THREAD: This is the Message %s\n", msg); } int main(void){ int error = 0; size_t i = 0; /* スレッドプールを作成 */ pthread_t thr[thread_no]; for (i = 0; i < thread_no; i++) { error = pthread_create( &(thr[i]), NULL, message_print, (void *) mess); /* エラー処理 */ } printf("MAIN: Thread Message: %s\n", mess); pthread_exit(NULL); }
適合コード
次の解決法では、終了時にリソースを回収できるように、message_print() 関数の代わりにスレッドを適切にデタッチできる同様の関数を使用している。
size_t const thread_no = 5; char mess[] = "This is a test"; void *message_print(void *ptr){ int error = 0; char *msg; /* スレッドをデタッチ */ error = pthread_detach(pthread_self()); /* もしあればエラー処理 */ msg = (char *) ptr; printf("THREAD: This is the Message %s\n", msg); } int main(void) { int error = 0; size_t i = 0; /* スレッドプールを作成 */ pthread_t thr[thread_no]; for(i = 0; i < thread_no; i++) { error = pthread_create( &(thr[i]), NULL, message_print, (void *) mess); /* エラー処理 */ } printf("MAIN: Thread Message: %s\n", mess); pthread_exit(NULL); }
リスク評価
ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
POS41-C | 低 | 低 | 高 | P2 | L3 |
参考資料
- [Open Group 2004]
- [pthread_detach]
翻訳元
これは以下のページを翻訳したものです。
POS41-C. When a thread exit status is not of concern, pthread_detach() or an equivalent function must be used (revision 25)