pthreadとスレッド終了時の動作について
PROCESS WARPでマルチスレッド対応、分散処理対応を行うためにpthreadの動作、特に終了処理について調査しました。 manを読みながら明記されていない部分をMacOSX環境でサンプルを作って確認しました。
- exitで終了した場合、子スレッドも終了される。
- atexitで登録した関数が終了前に呼び出される
- 子スレッドでatexitで関数を登録しても、プロセス終了時に親スレッドで実行される
- 子スレッドでexitを実行すると同一プロセスの全てのスレッドが終了する
- pthread_clean_pushで登録した関数はexit時は実行されない
- pthread_key_createで登録したデストラクタはexit時は実行されない
- 子スレッドだけ終了するにはpthread_exitを利用する。
- pthread_clean_pushで登録した関数がpthread_exitで実行される
- pthread_key_createで登録したデストラクタが実行される
- 関数が実行されるのはpthread_exitが呼び出されたか処理が終了したタイミングであり、joinのタイミングではない
- 大元のスレッドでもpthread_exitを呼び出せる
- pthread_clean_push、pthread_key_createで登録した関数が実行される
- その後atexitで登録した関数が実行される
- pthread_exit以降の処理は実行されない
- 正常終了扱いになる
- スレッドがmutexを保持したままpthread_exitやreturnで終了した場合、mutexはロック状態のままになる
- 他のスレッドからthread_mutex_unlockを呼び出せばロックは解除できる
- pthread_key_createで登録したデストラクタはpthread_setspecificでNULL以外を指定しているプロパティに対して呼び出される
- returnでスレッド終了しても呼び出される
- 大元のスレッドではreturn終了では呼び出されない
なので、
- atexitで登録した関数のスタックはプロセスで1つだけ
- pthread_key_createで登録したキー、デストラクタはプロセス内のスレッドで共通
- pthread_setspecificで登録した値はスレッドごとに保持される
- pthread_clean_pushで登録した関数はスレッドごとに保持される(スタックに積まれる)
- exitで終了時または大元のスレッドがreturnする場合は、スレッドごとの終了処理はされない
- pthread_exit呼び出し時はpthread_clean_push, pthread_key_createで登録した関数の順に呼び出す
- pthread_exitを呼び出したのが大元のスレッドの場合は、その後にプロセスの正常終了処理を行う
という作りになっているようです。