0

Here is my code:

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

static void sigint_handler(int signo){
    printf("%s\n", "hello world!");
    for(;;){
        pause();
    }
}

int main()
{
    signal(SIGINT, sigint_handler);
    for(;;){
        pause();
    }
    return 0;
}

And in action:

Korays-MacBook-Pro:~ koraytugay$ gcc tugay.c
Korays-MacBook-Pro:~ koraytugay$ ./a.out 
^Chello world!
^C^C^C^C^C^C

Why don't I see the hello world message after I hit CTRL + C for the second, third, forth time..?

My understanding is the process should catch CTRL C again, but obviously it is wrong. But why?

Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
  • The `man` page says: "The pause() function forces a process to pause until a signal is received from either the kill(2) function or an interval timer. (See setitimer(2).) Upon termination of a signal handler started during a pause(), the pause() call will return." – Fiddling Bits Jun 02 '15 at 19:42
  • You should not be using something like `printf()` inside a signal handler anyway - you are recommended to only use "Async-signal-safe" functions as per the section with that name in the man page for `signal(7)`- the problem is because may functions that you might be tempted to use can them self generate further signals which can be catastrophic in handlers...! – SlySven Feb 07 '17 at 16:50

3 Answers3

4

On BSD, when a signal handler is invoked, the signal disposition is not reset, and further instances of the signal are blocked from being delivered while the handler is executing.

And since mac osx is partly based on BSD, once the code is run on a mac osx, once second exception is called, it will be pending and wait for the handler of the first exception to exit. But since you will never exit, you have a deadlock.

Read my full explanation here

Community
  • 1
  • 1
Milan
  • 15,389
  • 20
  • 57
  • 65
1

Two facts:

  • when a signal is delivered, it is also blocked during execution of the handler (no SIGINT will be delivered while execution is in sigint_handler if it is called from SIGINT delivery);
  • signal is the historical interface, it is considered as obsolete, you must use sigaction.
Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
0

I have also found this in The GNU C Library Reference Manual:

When the signal is delivered, whether right away or after a long delay, the specified action for that signal is taken. For certain signals, such as SIGKILL and SIGSTOP, the action is fixed, but for most signals, the program has a choice: ignore the signal, specify a handler function, or accept the default action for that kind of signal. The program specifies its choice using functions such as signal or sigaction.

While the handler is running, that particular signal is normally blocked.

Koray Tugay
  • 22,894
  • 45
  • 188
  • 319