1

Let's say we have a program in C that uses the sleep() function.

The program executes and goes to sleep. Then we type Ctrl+c to send a SIGINT signal to the process.

We know that the default action upon receipt of a SIGINT is to terminate the process, we also know that the sleep function returns prematurely whenever the sleeping process receives a signal that is not ignored.

After we type Ctrl+c, does the sleep() function return first or the process gets terminated first?

1

The default action of SIGINT is to terminate the process according to the documentation (taken here from signal(7) on OpenBSD).

These signals are defined in the file <signal.h>:

Name         Default Action       Description
SIGHUP       terminate process    terminal line hangup
SIGINT       terminate process    interrupt program

Termination should, in theory, not give a process any chance to execute any more code. A simple litmus test may help to show what is going on (but does not prove that no code from the process is executed following an unhandled SIGINT).

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

void sigint(int sig)
{
    fprintf(stderr, "got INT\n");
}

void warnexit(void)
{
    fprintf(stderr, "atexit\n");
}

int main(void)
{
    atexit(warnexit);
    //signal(SIGINT, sigint);
    fprintf(stderr, "%d\n", getpid());
    sleep(640);
    fprintf(stderr, "ouch!\n");
    return 0;
}

With the signal(...) handler commented out, a control+c exits the program; there is no indication the atexit handler nor ouch line are run:

$ make sleepint
egcc -O2 -pipe    -o sleepint sleepint.c 
$ ./sleepint
31761
^C
$ 

With the signal(...) handler uncommented, the remainder of the code is reached:

$ make sleepint
egcc -O2 -pipe    -o sleepint sleepint.c 
$ ./sleepint 
64094
^Cgot INT
ouch!
atexit
$ 

Note however that SIGINT handling is in practice very complicated: shells and other processes will routinely have SIGINT handlers (otherwise the shell would exit, which could be bad), pressing control+c may not send a signal to the foreground process group (a program could put the terminal into raw mode with e.g. the ncurses cbreak() call and would instead see a ETX key), and different shells do different things when a complex command is hit with a control+c. Also with sigaction(2) one can use the SA_RESTART flag to change how various system calls behave...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.