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

CON37-C. マルチスレッドプログラムで signal() を呼び出さない

CON37-C. マルチスレッドプログラムで signal() を呼び出さない

マルチスレッドプログラム内での signal() 関数の呼び出しは、C11(セクション7.14.1.1、パラグラフ7)に従うと未定義の動作である。

このルールは、「SIG02-C. 標準的な機能を実装する際はシグナルの使用を避ける」の具体的な例である。

違反コード

このコードはシグナルハンドラを設定し、一方で子スレッドが動作するように設定している。この結果、未定義の動作となる。

volatile sig_atomic_t flag = 0;

void handler(int signum) {
  flag = 1;
}


void func(void *data) {  // keep running until user sends SIGUSR1
  while (!flag) {
    /* ... */
  }
}


int main(void) {
  signal(SIGUSR1, handler); // Undefined!
  int result;
  thrd_t thread;
  
  int result;
  if ((result = thrd_create(&tid, func, NULL)) != thrd_success) {
    /* エラー処理 */
  }

  /* ... */

  return 0;
}
適合コード

このコードはシグナルハンドラなしで、atomic_flag を使用して子スレッドがループを終了したタイミングを示している。

atomic_flag flag = ATOMIC_VAR_INIT;


void func(void *data) {  // keep running until user sends SIGUSR1
  while (!flag) {
    /* ... */
  }
}


int main(void) {
  int result;
  thrd_t thread;
  
  int result;
  if ((result = thrd_create(&tid, func, NULL)) != thrd_success) {
    /* エラー処理 */
  }


  /* ... */


  /* 完了時にフラグをセット */
  while (!atomic_flag_test_and_set( &flag)) { /* try again */ }


  return 0;
}
例外

CON37-EX0: マルチスレッドプログラムがカスタムシグナルハンドラを使用している場合に定義された動作を提供するプラットフォームには、このルールは適用されない。これには、たとえば、POSIXが含まれる。

リスク評価

シグナルとスレッドの混在は未定義の動作につながる。

ルール

深刻度

可能性

修正コスト

優先度

レベル

CON37-C

P6

L2

参考資料
[ISO/IEC 9899:2011]  
翻訳元

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

CON37-C. Do not call signal() in a multithreaded program (revision 45)

Top へ

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