Дамп ядра с плавающей запятой - PullRequest
10 голосов
/ 08 июля 2011

Я новичок в сигналах Linux, пожалуйста, помогите. Следующий код получает дамп ядра при запуске в Linux 2.6 gcc.

$ ./a.out
Исключение с плавающей точкой (ядро сброшено)

Вопросы:
1. Поскольку маска сигнала процесса установлена, не должен ли блокироваться «SIGFPGE», генерируемый линией 40 volatile int z = x/y;?
2. Если он не заблокирован, поскольку установлен обработчик сигнала, не должен ли обработчик сигнала захватывать «SIGFPE» вместо дампа памяти?
3. Если я закомментировал строку 40 volatile int z = x/y; и использовал вместо нее строку 42 raise(SIGFPE);, тогда все работает, как я ожидал. В чем разница между х / 0 и рейзом SIGFPE здесь?

Вот код:

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

    void sig_handler(int signum)
    {
       printf("sig_handler() received signal %d\n", signum);
    }


    int main(int argc, char * argv[])
    {

       // setup signal mask, block all signals
       sigset_t set;
       sigfillset(&set);

       if(sigprocmask(SIG_BLOCK, &set, NULL)<0)
       {
          perror("failed to set sigmask");
          return -1;
       }

       // install signal handler for SIGFPE
       struct sigaction act;
       act.sa_handler = sig_handler;
       act.sa_mask = set;
       act.sa_flags = 0;
       if(sigaction( SIGFPE, &act, NULL)<0)
       {
          perror("sigaction failed");
          exit(-1);
       }

       volatile int x =1;
       volatile int y =0;
       volatile int z = x/y; //line 40

       //raise(SIGFPE); //line 42

       printf("point 1000\n");

       return 0;
    }

Ответы [ 2 ]

4 голосов
/ 08 июля 2011

Любой SIGFPE, вызванный аппаратной ловушкой во время блокировки сигнала, вызывает неопределенное поведение:

Если какой-либо из сигналов SIGFPE, SIGILL, SIGSEGV или SIGBUS генерируется во время их блокировки, результат не определен, если только сигнал не был сгенерирован функцией kill (), функцией sigqueue () или повышением ( ) функция.

(из sigprocmask спецификация )

0 голосов
/ 04 июля 2019

man signal

Согласно POSIX, поведение процесса не определено после того, как он игнорирует сигнал SIGFPE, SIGILL или SIGSEGV, который не был сгенерирован kill (2) или Повышать (3).Целочисленное деление на ноль имеет неопределенный результат.

На некоторых архитектурах он генерирует сигнал SIGFPE.(Также деление самого отрицательного целого числа на -1 может генерировать SIGFPE).Игнорирование этого сигнала может привести к бесконечной петле.

Я обнаружил это после попытки выяснить, почему отрицательная / положительная бесконечность возникла в результате деления на ноль: IEEE 754, деление на ноль

Это место, которое вы никогда не хотите получить:

void divZeroHdlr(int sig) {
  printf("div by zero: %d\n",sig)
  exit(1);}

int main(int argc, char *argv[]) {
  signal(SIGFPE, divZeroHdlr)
  int n = 1/0}
...