Когда ядро ​​Linux сбросит обработчик сигнала для SIGSEGV в SIG_DFL? - PullRequest
0 голосов
/ 13 ноября 2018

Если я установил обработчик сигнала для SIGSEGV, тогда как ошибка сегментации генерируется как:

int *a = NULL;
*a = 1;

Обработчик будет вызываться, но этот обработчик сигнала будет вызываться только один раз.Итак, я предполагаю, что ядро ​​Linux сбросит обработчик сигнала на SIG_DFL, но когда?Я хочу знать подробности, поэтому я проверил исходный код ядра Linux, но пока не смог найти подсказку.Пожалуйста, покажите мне код, если вы знаете детали.

Ответы [ 2 ]

0 голосов
/ 14 марта 2019

Как справедливо ответил @PSkocik, в обычных сценариях ядро ​​не будет беспокоиться о том, чтобы изменить действие сигнала на значение по умолчанию, если пользователь не установил обработчик сигнала с флагом SA_RESETHAND в sigaction,.

Однако существует сценарий, в котором ядро ​​изменяет действие сигнала SIGSEGV на значение по умолчанию. Предположим, пользователь установил обработчик сигнала, а затем исчерпал всю память, прежде чем генерировать сигнал. В этом случае ядро ​​не сможет создать фрейм для выполнения обработчика сигнала, так как не осталось памяти. После обнаружения этой ситуации ядро ​​делает следующее:

  1. Проверьте, установил ли пользователь обработчик для SIGSEGV. Если да, изменяет действие на значение по умолчанию и разблокирует SIGSEGV, если пользователь заблокировал его.
  2. Доставить SIGSEGV сигнал пользователю о прекращении пользовательского процесса.
0 голосов
/ 13 ноября 2018

Зависит от того, как вы регистрируете обработчик сигнала. С sigaction и без флага SA_RESETHAND сброса на SIG_DFL не будет (хотя возврат из обработчика сигнала в ответ на SIGSEGV, доставленный из-за ошибки сегментации, технически является UB). С SA_RESETHAND он будет сброшен, и если вы зарегистрируете обработчик с помощью signal, то будет ли указываться обработчик сброса или нет, поэтому не используйте signal().

Пример:

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

int volatile*a;
void h(int Sig) { write(1,"h\n", 2); }
int main()
{
    //sigaction(SIGSEGV,&(struct sigaction){.sa_handler=h}, 0); //won't reset the handler, will likely loop
    sigaction(SIGSEGV,&(struct sigaction){.sa_handler=h,.sa_flags=SA_RESETHAND}, 0); //will reset the handler
    //signal(SIGSEGV,h); //may or may not reset the handler
    *a=1;
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...