Introduction to Signals Using Alarm() in Linux C

A signal is the software equivalent of a hardware interrupt. Signals provide a means for handing asynchronous events, with asynchronous here meaning “unpredictable”.

There are several dozen different signals, each with a different meaning. Every one of these signals has a name, beginning with the three letters SIG. Each signal is specified by its number, but we mostly use signals by their names. To utilize signals, we must include the header file signal.h.

The most commonly used signals are SIGHUP, SIGQUIT, SIGKILL, and SIGTERM. Each of these signals has a numeric value. SIGKILL, 9, is perhaps the most notorious, as it issues an unblockable kill signal.

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

int main(void){

    printf("SIGHUP = %d\n", SIGHUP);
    printf("SIGQUIT = %d\n", SIGQUIT);
    printf("SIGKILL = %d\n", SIGKILL);
    printf("SIGTERM = %d\n", SIGTERM);

    return 0;


}

Every signal has a default action associated with it; this is known as the signal’s disposition.

The alarm() function sets a timer that generates the SIGALARM signal. If we ignore or don’t catch this signal, the process is terminated.

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

static void alarmHandler(int signo);

int main(void){

    alarm(5);

    signal(SIGALRM, alarmHandler);

    for(int i = 1; i < 10; i++){
        printf("%d\n", i);
        sleep(1);    
    }

    return 0;

}

static void alarmHandler(int signo){
    printf("Alarm signal sent!\n");

}

Note that there is only one alarm clock per process. While the default action for SIGLARM is to terminate the process, usually we will want to catch this signal.

The wait() function will cause a process to wait until a child process terminates.

#include <stdio.h>
#include <stdlib.h> //for exit() function
#include <unistd.h>
#include <signal.h>
#include <wait.h>
#include <sys/types.h>

static void catchAlarm(int signo);

int main(void){

    int status;
    pid_t pid;
    
    signal(SIGALRM, catchAlarm);
    pid = fork();

    if(pid < 0){
        printf("Problem forking process.\n");
        printf("Exiting now...\n");
        exit(EXIT_FAILURE);
    }

    if(pid==0){
        alarm(5);
        for(int i = 0; i < 7; i++){
            printf("In child process... %d\n", i);
            sleep(1);
        }
    } else     {
        wait(&status);
        alarm(7);
        for(int i = 0; i < 15; i++){
            printf("In parent process... %d\n", i);
            sleep(1);
        }
    }

}


static void catchAlarm(int signo){
    printf("Caught an SIGALRM signal.\n");
    printf("Signal value = %d\n", signo);

    printf("Exiting from process...\n");

    //in stdlib.h header file
    exit(EXIT_SUCCESS);

}

Note that the alarm() function will return a value if another alarm has been previously set.

The pause() function suspends the process until a signal is caught.

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

static void catchSignal(int signo);

int main(void){

    alarm(7);

    signal(SIGALRM, catchSignal);

    //remember, a process can have
    //only one alarm
    if(alarm(5) > 0){
        printf("An alarm has already been set.\n");
    }

    pause();

    printf("We should not see this text.\n");

    return 1;
}

static void catchSignal(int signo){
    printf("Caught the %d signal\n", signo);
    printf("Exiting now...\n");

    exit(EXIT_SUCCESS);
}

Remember, a process can have only one alarm.

 

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s