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

CON05-C. ロックを保持している状態ではブロックする可能性がある操作を行わない

ロックが保持されている状態でブロックする可能性がある操作を行うと、そのロックを取得する必要がある他のスレッドもブロックする可能性がある。この状態は、システム性能の低下やデッドロックの発生につながる可能性がある。ブロックする可能性がある操作の例としては、ネットワーク I/O、ファイル I/O、コンソール I/O がある。

実際には、ロックを保持したままブロックする可能性のある操作を行うことは避けられないだろう。例えば、ファイルアクセス時に他のスレッドによるファイル変更を防ぐためにロックをかけたり、スレッドが複数のロックを順番に取得しなければならない状況が考えられる。これらの状況では、ロックを保持する時間は可能なかぎり短くすること。さらに複数のロックを取得する場合には、デッドロックが発生しないよう、取得する順番に注意しなければならない。「CON35-C. あらかじめ定義した順番でロックしてデッドロックを防ぐ」を参照。

違反コード

以下のコード例では、ミューテックスがロックされている状態で fopen() を呼び出している。fopen()fclose() 呼出しはブロックする可能性がある。ファイルアクセスがネットワーク越しに行われる場合には、ブロックする時間は長くなるかもしれない。ファイル操作の呼出しがブロックしている間、ロックを取得しようとする他のスレッドもブロックすることになる。

#include <stdio.h>
#include <threads.h>

mtx_t mutex;

int thread_foo(void *ptr) {
  int result;
  FILE *fp;

  if ((result = mtx_lock(&mutex)) != thrd_success) {
    /* エラー処理 */
  }

  fp = fopen("SomeNetworkFile", "r");
  if (fp != NULL) {
    /* ファイル操作 */
    fclose(fp);
  }

  if ((result = mtx_unlock(&mutex)) != thrd_success) {
    /* エラー処理 */
  }

  return 0;
}

int main(void) {
  thrd_t thread;
  int result;

  if ((result = mtx_init(&mutex, mtx_plain)) != thrd_success) {
    /* エラー処理 */
  }

  if (thrd_create(&thread, thread_foo, NULL) != thrd_success) {
    /* エラー処理 */
  }

  /* ... */

  if (thrd_join(thread, NULL) != thrd_success) {
    /* エラー処理 */
  }

  mtx_destroy(&mutex);

  return 0;
}
適合コード (ロックされていない状態でのブロック)

以下の適合コードは、ロックを取得していないときにファイル操作を行う。このため、操作がブロックしたときの影響は、ブロックする関数を呼び出したスレッドに限定される。

#include <stdio.h>
#include <threads.h>

mtx_t mutex;

int thread_foo(void *ptr) {
  int result;
  FILE *fp = fopen("SomeNetworkFile", "r");

  if (fp != NULL) {
    /* ファイル操作 */
    fclose(fp);
  }

  if ((result = mtx_lock(&mutex)) != thrd_success) {
    /* エラー処理 */
  }

  /* ... */

  if ((result = pthread_mutex_unlock(&mutex)) != 0) {
    /* エラー処理 */
  }

  return 0;
}
リスク評価

同期された領域内部で操作がブロックしたり長時間におよぶ操作を実行したりすると、システムのデッドロックや応答停止が発生する可能性がある。

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

CON05-C

P2

L3

関連するガイドライン
CERT Oracle Secure Coding Standard for Java LCK09-J. 途中で待機状態になる可能性のある操作をロックを保持したまま実行しない
翻訳元

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

CON05-C. Do not perform operations that can block while holding a lock (revision 21)

Top へ

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