Дамп ядра с плавающей запятой

Я новичок в сигналах 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;
    }

Ответ 1

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

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

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

Ответ 2

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}