JPCERT コーディネーションセンター

POS04-C. PTHREAD_MUTEX_NORMAL ミューテックスロックの使用を避ける

pthread 相互排他(ミューテックス)ロックは、共有資源の同時使用を避けるために使われる。次の種類のミューテックスロックがpthread によって定義されている:NORMALERRORCHECKRECURSIVEDEFAULT

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
参考資料
翻訳元

これは以下のページを翻訳したものです。

POS04-C. Avoid using PTHREAD_MUTEX_NORMAL type mutex locks (revision 16)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter