выполнение обработчика сигналов по умолчанию - PullRequest
19 голосов
/ 16 мая 2011

Я написал приложение, в котором зарегистрировал номер обработчика сигналов для разных сигналов в Linux. После того, как процесс получает сигнал, управление передается зарегистрированному обработчику сигнала. В этом обработчике сигналов я делаю некоторую работу, которую мне нужно сделать, и затем я хотел бы вызвать хендер по умолчанию, т. Е. SIF_DFL или SIG_IGN. Однако SIG_DFL и SIG_ING являются макросами, которые расширяются до числовых значений 0 и 1 соответственно, которые являются недопустимыми адресами функций.

Есть ли способ вызвать действия по умолчанию, т.е. SIG_DFL или SIG_IGN?

Чтобы добиться эффекта SIG_DFL или SIG_ING, я вызываю exit (1) и ничего не делаю, соответственно. Но для сигналов типа SIGSEGV я также хотел бы иметь дамп ядра. В общем, я хотел бы, чтобы мое поведение по умолчанию было таким же, как SIG_DFL, и игнорировало бы поведение таким же SIG_IGN, как это делала бы операционная система.

Ответы [ 4 ]

13 голосов
/ 08 ноября 2012

Справочное руководство по библиотеке GNU C имеет целую главу, объясняющую все об обработке сигналов.

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

previous_handler = signal(SIGINT, myhandler);

Общее правило: вы всегда можете вернуться к предыдущему обработчику и raise() повторить сигнал.

void myhandler(int sig) {
  /* own stuff .. */
  signal(sig, previous_handler);
  raise(sig);
  /* when it returns here .. set our signal handler again */
  signal(sig, myhandler);
}

Существует один недостаток общего правила: аппаратные исключения, которые сопоставляются с сигналами, обычно присваиваются определенной инструкции, которая вызвала исключение.Таким образом, когда вы снова подаете сигнал, соответствующая инструкция не совпадает с исходной.Это может, но не должно наносить вред другим обработчикам сигналов.

Еще один недостаток заключается в том, что каждый повышенный сигнал вызывает много времени обработки.Для предотвращения чрезмерного использования raise() вы можете использовать следующие альтернативы:

  1. В случае SIG_DFL указатель функции указывает на адрес 0 (который, очевидно, не является действительным адресом),Таким образом, вам необходимо сбросить обработчик и raise() сигнал снова.

    if (previous_handler == SIG_DFL)
    {
      signal(sig, SIG_DFL);
      raise(sig);
      signal(sig, myhandler);
    } 
  2. SIG_IGN имеет значение 1 (также недействительный адрес).Здесь вы можете просто вернуться (ничего не делать).

    else if (previous_handler == SIG_IGN)
    {
      return;
    } 
  3. В противном случае (ни SIG_IGN, ни SIG_DFL) вы получили действительный указатель на функцию, и вы можете напрямую вызвать обработчик,

    else
    {
      previous_handler(sig);
    }

Конечно, вы также должны учитывать различные API (см. Справочные страницы для signal() и sigaction()).

10 голосов
/ 16 мая 2011

Вы можете сохранить предыдущий обработчик и затем вызвать его, когда настанет время.

Установить обработчик.Убедитесь, что вы сохранили старый обработчик

static struct sigaction new_sa, old_sa;

new_sa.handler = my_handler;
sigemptyset(&new_handler.sa_mask);

if (sigaction(signo, &new_sa, &old_sa) == -1) {
    /* handle sigaction error */
}

В вашем новом обработчике вызовите старый обработчик

(*old_sa.sa_handler)(signo)

Вам не нужно поднимать егоснова или делать беспорядочные вещи;просто вызовите старый обработчик (конечно, поскольку вы сохранили sigaction, у вас есть доступ к старому расположению и т. д.).

6 голосов
/ 16 мая 2011

Обычный подход состоит в том, чтобы сбросить обработчик сигнала, а затем raise() сигнал снова:

Вот пример обработчика SIGINT:

void sigint_handler(int num)
{
    /* handle SIGINT */

    // call default handler
    signal(SIGINT, SIG_DFL);
    raise(SIGINT);
}
2 голосов
/ 16 мая 2011

Учитывая, что обработчики сигналов реализованы в ядре, я вижу только

  • сбросить обработчик и
  • raise() сигнал снова
...