Introduction

The pause() system call is used to make the calling process or thread sleep until one of the following events occurs:

  • The calling process receives the signal whose default behaviour is to kill the process. (OR)
  • The execution of the signal handler is completed

In both the cases, the pause() system call returns -1.

/assets/linux/man2/pause.png

Behaviour when the process catches a signal

Let’s examine the following program.

file: pause.c

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

int main(void)
{
        int ret = 0;
        ret = pause();
        printf("Pause returned with %d\n", ret);
        return 0;
}

Compile the program using:

gcc pause.c -o pause

Run the program with ./pause. The program sleeps at the line ret = pause();. From another terminal, send signals to this process using the kill command.

Examples:

kill -SIGKILL `pidof pause`	# Kills the process
OR
kill -SIGCHLD `pidof pause`	# Won't have any effect

The signals SIGCHLD, SIGCONT, SIGSTOP won’t terminate the process, as their default behavior is not set to do so. Additionally, the program does not register signal handlers for these signals, so the pause() system call won’t return upon catching these signals.

However, the pause() function returns when it receives signals with default behaviors set to terminate the process, such as SIGKILL, SIGTERM, etc. For more information on signals and their default behaviors, please run the man 7 signal command.

Behavior when the process finishes executing the signal handler

Let’s examine the following program.

file: pause_sigaction.c

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

void signal_handler(int signal)
{
        printf("Signal %d caught\n", signal);
}

int main(void)
{
        struct sigaction act;
        int ret = 0;

        act.sa_handler =  signal_handler;
        sigaction(SIGCONT, &act, NULL);
        ret = pause();
        if (-1 == ret)
                printf("Process exited\n");
        return 0;
}

A signal handler has been registered for the signal SIGCONT. When we pass this signal to the process, the signal_handler function is called. In this case, the pause() returns when the signal_handler completes execution. This holds true for all signals, whether the default behavior of the signal is to terminate the process or not.

Let’s compile the program with:

gcc pause_sigaction.c -o pause_sigaction

Execute the program with ./pause_sigaction in one terminal and in other terminal run the following command to send SIGCONT signal to the process.

kill -SIGCONT `pidof pause_sigaction`

The pause() returns, and the signal number is printed in the signal_handler(), after which the process exits.

Replace SIGCONT with SIGALRM, whose default behaviour is to terminate the process, in the above program. Re-compile and run the program. Pass the SIGALRM signal to the process using the kill command. The same behaviour can be observed.