メインコンテンツ

信号ハンドラー内でのデータ アクセスの共有

共有データへのアクセスまたは変更による不整合状態の発生

説明

この欠陥は、信号ハンドラー内の共有オブジェクトへのアクセスまたは変更を行った場合に発生します。

リスク

共有オブジェクトへのアクセスまたは変更を行う信号ハンドラー関数を定義する場合、ハンドラーは信号を受け取ると共有オブジェクトへのアクセスまたは変更を行います。他の関数が既にその共有オブジェクトにアクセス中の場合、その関数が競合状態を発生させ、データが不整合状態になる可能性があります。

修正方法

信号ハンドラー内の共有オブジェクトへのアクセスまたは変更を行うには、オブジェクトがロック制御不要のアトミックであることをチェックするか、オブジェクトが整数の場合は volatile sig_atomic_t として宣言します。

すべて展開する

#include <signal.h>
#include <stdlib.h>
#include <string.h>

/* declare global variable. */
int e_flag;

void sig_handler(int signum)
{
	/* Signal handler accesses variable that is not
	of type volatile sig_atomic_t. */
    e_flag = signum; 
}

int func(void)
{
    if (signal(SIGINT, sig_handler) == SIG_ERR)
    {
        /* Handle error */
        abort();
    }
    /* Program code */
    if (raise(SIGINT) != 0)
    {
        /* Handle error */
        abort();
    }
    /* More code */
    return 0;
}
        
      

この例では、sig_handlerint 型の変数である e_flag にアクセスしています。別の関数からの同時アクセスによって、e_flag が不整合状態になる可能性があります。

修正 — volatile sig_atomic_t 型の変数を宣言

信号ハンドラーから共有変数にアクセスする前に、変数を int 型ではなく volatile sig_atomic_t 型で宣言します。この型の変数には非同期で安全にアクセスできます。

#include <signal.h>
#include <stdlib.h>
#include <string.h>

/* Declare variable of type volatile sig_atomic_t. */
volatile sig_atomic_t e_flag;
void sig_handler(int signum)
{
	/* Use variable of proper type inside signal handler. */
    e_flag = signum;
    
}

int func(void)
{
    if (signal(SIGINT, sig_handler) == SIG_ERR)
    {
        /* Handle error */
        abort();
    }
    /* Program code */
    if (raise(SIGINT) != 0)
    {
        /* Handle error */
        abort();
    }
    /* More code */
    return 0;
} 

結果情報

グループ: プログラミング
言語: C | C++
既定値: 手書きコードはオン、生成コードはオフ
コマンド ライン構文: SIG_HANDLER_SHARED_OBJECT
影響度: Medium

バージョン履歴

R2017b で導入