Unix Signal Handlers
Signal Processing
In this lab, you will demonstrate your knowledge of signal processing in Unix (signal or
sigaction). You are required to write a C program that contains three signal handler
functions:
(1) The first is to handle the SIGINT (CTRL-C) signal. This signal handler should
increment a counter and when the program finally completes, the program should
output the number of times the user depressed CTRL-C. In addition, the signal handler
should also contain a MAX value (say 5) that is invoked if the user exceeds this
maximum. In this case, a message indicating that the MAX has been exceeded should
be output and the signal should not be reinstalled so the next instance will cause the
program to terminate.
(2) The second signal handler should deal with the SIGQUIT signal (CTRL-\). If the user
sends this signal, the signal handler should create a new process (fork). The child
process should print a message and then send a SIGUSR1 signal (using kill() see slide
9) to its parent then the child should terminate with no error code. The parent should
simply wait for the child to terminate.
(3) The final signal handler should catch the SIGUSR1 signal (sent by the child
process). This handler should print a message that the program is over and then exit.
The main program should contain a loop forever waiting for a signal (i.e. pause).
Sample output of your program might look something like:
jacques@loki:~]$ ./lab5
Wait for another signal …
^CThis is the 1 time you pressed ctrl-c
Wait for another signal …
^CThis is the 2 time you pressed ctrl-c
Wait for another signal …
^CThis is the 3 time you pressed ctrl-c
Wait for another signal …
^CThis is the 4 time you pressed ctrl-c
Wait for another signal …
^\I am the child and I am sending a signal
Child sent a signal so I guess you are bored, have a great day!
Solution
//Libraries
#include //The signal library
#include //standard library
#include //printf Standard InputOutput Library
#include //pid, cwd, fork
//Global Vars
staticintconst MAX_COUNT = 5; //Max number of sigints to recieve before removing the sigint handler
intsigintCounter = 0; //Used to show how many sigint signals recieved
pid_tchild_pid; //child process id
//Prototypes
voidsigintHandler(intsigint);
voidsigquitHandler();
voidsiguserHandler();
//Main
//Listen for the three different types of sigints (SIGINT, SIGQUIT, SIGUSR1)
int main(intargc, char* argv[])
{
if (!child_pid)
{
//Parent functionality
//Handlers
signal(SIGINT, sigintHandler); //ctrl-c
signal(SIGQUIT, sigquitHandler); //ctrl-slash
signal(SIGUSR1, siguserHandler); //user defined
//Forever loop while we wait for signals
do
{
printf(“Wait for another signal … \n”);
pause(); //wait
} while (1);
}
}
//SIGINT HANDLER (ctrl-c)
// Param: sigint the number emitted (1-3) : not used in this
voidsigintHandler(intsigint)
{
sigintCounter++; //increment the counter
//Check if we reached the total number of sigint counts
if (sigintCounter>= MAX_COUNT)
{
//Done
printf(“SIGINT: MAX has been exceeded\n”);
signal(SIGINT, SIG_DFL); //use the default sigint handler
} else
{
printf(“This is the %d time you pressed cntl-c\n”, sigintCounter);
signal(SIGINT, sigintHandler); //readd the custom handler
}
}
//SIGQUIT HANDLER (ctrl-\)
voidsigquitHandler()
{
//Fork the process and create a child process
if (!(child_pid = fork()))
{
// Child: Print message
printf(“I am the child(%d) and I am sending a signal to parent(%d)\n”, getpid(), getppid());
// Child: KILL() to parent
kill(getppid(), SIGUSR1); //send signal
exit(0); //child process exit
} else
{
//Parent message
printf(“Parent(%d): I have a child %d\n”, getpid(), child_pid);
}
}
//SIGUSR1 (sent by child process)
voidsiguserHandler()
{
printf(“Parent(%d): Child sent signal. We are finished\n”, getpid());
exit(0); //Exit parent process
}