POS04-C. PTHREAD_MUTEX_NORMAL ミューテックスロックの使用を避ける
pthread 相互排他(ミューテックス)ロックは、共有資源の同時使用を避けるために使われる。次の種類のミューテックスロックがpthread によって定義されている:NORMAL、ERRORCHECK、RECURSIVE、DEFAULT。
POSIX には、PTHREAD_MUTEX_NORMAL ロックについて、次の未定義の動作があると記載されている [Open Group 2004]。
この種のミューテックスにはデッドロックを検出する機能がない。この種のミューテックスをアンロックせずに再ロックしようとすると、デッドロックを引き起こす。呼び出し元にエラーは返されない。異なるスレッドによってロックされているミューテックスをアンロックしようとすると、未定義の動作が引き起こされる。ロックされていないミューテックスをアンロックしようとすると、未定義の動作が引き起こされる。
DEFAULT ミューテックスは、通常は PTHREAD_MUTEX_NORMAL に割り当てられるが、プラットフォームによって異なることがわかっている[SOL 2010]。それゆえ、NORMAL ロックを使用すべきではない。ミューテックスロックを使用するときには、ERRORCHECK ロックまたは RECURSIVE ロックを明示的に定義する必要がある。
違反コード
以下のコード例は、PTHREAD_MUTEX_NORMAL を使用して作成された単純なミューテックスを示している。
pthread_mutexattr_t attr; pthread_mutex_t mutex; size_t const shared_var = 0; int main(void) { int result; if ((result = pthread_mutexattr_settype(&mutex, {{PTHREAD_MUTEX_NORMAL}})) != 0) { /* エラー処理 */ } if ((result = pthread_mutex_init(&mutex, &attr)) != 0) { /* エラー処理 */ } if ((result = pthread_mutex_lock(&mutex)) != 0) { /* エラー処理 */ } /* クリティカルな領域 */ if ((result = pthread_mutex_unlock(&mutex)) != 0) { /* エラー処理 */ } return 0; }
適合コード
次の解決法は、ロックおよびアンロックの際にリターンコードを利用できるように ERRORCHECK ミューテックスロックを使用している。
pthread_mutexattr_t attr; pthread_mutex_t mutex; size_t const shared_var = 0; int main(void) { int result; if ((result = pthread_mutexattr_settype(&mutex, PTHREAD_MUTEX_ERRORCHECK)) != 0) { /* エラー処理 */ } if ((result = pthread_mutex_init(&mutex, &attr)) != 0) { /* エラー処理 */ } if ((result = pthread_mutex_lock(&mutex)) != 0) { /* エラー処理 */ } /* クリティカルな領域 */ if ((result = pthread_mutex_unlock(&mutex)) != 0) { /* エラー処理 */ } return 0; }
リスク評価
NORMAL ミューテックスロックの使用は、デッドロックやプログラムの異常終了につながる可能性がある。
レコメンデーション | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
POS04-C | 低 | 低 | 中 | P1 | L3 |
参考資料
- [Open Group 2004]
- [SOL 2010]
翻訳元
これは以下のページを翻訳したものです。
POS04-C. Avoid using PTHREAD_MUTEX_NORMAL type mutex locks (revision 16)