メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

CERT C: Rule SIG34-C

中断可能な信号ハンドラー内から signal() を呼び出さない

説明

ルール定義

中断可能な信号ハンドラー内から signal() を呼び出さないようにします。1

Polyspace 実装

ルール チェッカーは、"信号ハンドラー内からの信号呼び出し" をチェックします。

すべて展開する

問題

信号ハンドラー内からの信号呼び出しは、Windows® プラットフォームで信号ハンドラーから関数 signal() を呼び出す場合に発生します。

この問題は、Visual Studio コンパイラを指定した場合にのみ検出されます。コンパイラ (-compiler) を参照してください。

リスク

関数 signal() は、信号と信号ハンドラー関数を関連付けます。信号の受信後にこの関連付けが削除される Windows などのプラットフォーム上では、"信号ハンドラー内で" 再度関数 signal() を呼び出して、関連付けを再設定することができます。

ただし、信号ハンドラーを永続的にするこの試みによって、競合状態が引き起こされやすくなります。Windows プラットフォームでは、信号ハンドラーが実行を開始してから、関数 signal が再度呼び出されるまでの間に、アクティブになっているのは既定の信号処理 SIG_DFL です。この間に 2 つ目の信号が受信されると、ユーザーの期待に反して、カスタム信号ハンドラーではなく既定の信号ハンドラーが示されます。

修正方法

Windows プラットフォームでは信号ハンドラーから signal() を呼び出さないようにします。

例 - 信号ハンドラーからの signal() の呼び出し
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>



volatile sig_atomic_t e_flag = 0;

void sig_handler(int signum)
{
    int s0 = signum;
    e_flag = 1;
	
	/* Call signal() to reestablish sig_handler 
	upon receiving SIG_ERR. */
   
    if (signal(s0, sig_handler) == SIG_ERR)  //Noncompliant
    {
        /* Handle error */       
    }
}

void func(void)
{
        if (signal(SIGINT, sig_handler) == SIG_ERR)
        {
            /* Handle error */
            
        }
  /* more code */
}        
      

この例では、sig_handler() の定義にハンドラーが SIG_ERR をキャッチした際の signal() の呼び出しが含まれています。Windows プラットフォームでは、信号ハンドラーは永続的ではありません。このコードは、競合状態を発生させる可能性があります。

この問題は、visual15.x などのコンパイラを解析用として指定した場合にのみ検出されます。

修正 — 信号ハンドラーから signal() を呼び出さない

Windows 上で信号ハンドラーを永続的にする試みを避けます。コードで Windows プラットフォームで永続的な信号ハンドラーを使用する必要がある場合、徹底的なリスク解析をしてから永続的な信号ハンドラーを使用します。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>



volatile sig_atomic_t e_flag = 0;


void sig_handler(int signum)
{
    int s0 = signum;
    e_flag = 1;
    /* No call to signal() */
}

int main(void)
{
    
        if (signal(SIGINT, sig_handler) == SIG_ERR)
        {
            /* Handle error */
            
        }
}
 

チェック情報

グループ: Rule 11.信号 (SIG)

バージョン履歴

R2019a で導入


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.