Signal call from within signal handler

Нестойкий обработчик сигнала, вызывая signal() в Windows система вызывает состояние состязания

Описание

Этот дефект происходит, когда вы вызываете функциональный signal() от обработчика сигнала на платформах Windows®.

Дефект обнаруживается, только если вы задаете компилятор Visual Studio. Смотрите Compiler (-compiler).

Риск

Функциональный signal() сопоставляет сигнал с функцией-обработчиком сигнала. На платформах, таких как Windows, который удаляет эту ассоциацию после получения сигнала, вы можете вызвать функциональный signal() снова в обработчике сигнала, чтобы восстановить ассоциацию.

Однако эта попытка сделать обработчик сигнала персистентным подвержена условиям состязания. На платформах Windows со времени обработчик сигнала начинает выполнение к когда signal функция вызвана снова, это - обработка сигнала по умолчанию, SIG_DFL, это активно. Если второй сигнал получен в этом окне времени, вы видите обработку сигнала по умолчанию а не пользовательский обработчик сигнала, но вы можете ожидать в противном случае.

Фиксация

Не вызывайте signal() от обработчика сигнала на платформах 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;
	
	/* Call signal() to reestablish sig_handler 
	upon receiving SIG_ERR. */
   
    if (signal(s0, sig_handler) == SIG_ERR) 
    {
        /* Handle error */       
    }
}

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

В этом примере, определении sig_handler() включает вызов signal() когда обработчик отлавливает SIG_ERR. На платформах 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 */
            
        }
}
 

Информация о результате

Группа: Программирование
Язык: C | C++
Значение по умолчанию: На для рукописного кода, прочь для сгенерированного кода
Синтаксис командной строки: SIG_HANDLER_CALLING_SIGNAL
Удар: Средняя
ID CWE: 387, 474
Введенный в R2017b