Вызов сигнала из обработчика сигнала

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

Описание

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

Риск

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

Фиксация

Не вызывайте 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 обработчики сигнала являются нестойкими. Этот код может привести к состоянию состязания.

Исправление — не вызывает 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;
    /* 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