Wednesday, February 15, 2006

Signal Handler

Consider that you have written a C program. Compile that and run it on a Linux Machine. When the program is executing, press Ctrl + C, the program execution stops. Suppose, if someone asks you to avoid this kind of termination of your program, What will you do?

First we can see what exactly happened when you pressed Ctrl + C. When Ctrl + C is pressed, a signal is generated. Now, what is a signal?? Signals are software interrupts sent to a process for notifying the process about some events. They interrupt whatever the process is doing at that time, and force it to handle them immediately. Each signal has an integer number that represents it (1, 2 and so on), as well as a symbolic name that is usually defined in the file /usr/include/signal.h.

You can write a signal handler for a particular signal. This signal handler function gets called when that particular signal occurs. The operating system transfers the control directly to this signal handler and once the signal handler has finished executing, the control returns back to whatever line of code that was executed previously. So how to you pass signals? well, Ctrl + C is just one method of passing a signal. We can do the same by using kill - or through the system call like kill(PID, SIGNAL).

To write your own signal handler, you need to use the following function.

void (*signal(int sig, void (*func)(int)))(int);

I know this is looking pretty complex. But the usage is not all that difficult. Signal function actually returns a function pointer. The first argument is the Signal number for which this particular signal handler has been written. Next is the pointer to the signal handler function. The signal handler function should take only one interger argument and should not return anything.

signal (SIGINT, sig_int_handler);

void sig_int_handler(int sig)
// your code goes here.

The signal call returns the previous signal handler pointer in case of success or SIG_ERR in case of failure. so check for the return value.
if (signal (SIGINT, sig_int_handler)==SIGERR)
printf("Error handling signal");

So consider you have written your signal handler to catch SIGINT (consider that it prints some warning msg) and program execution continues. When you run your program, and if Ctrl + C is pressed( which is same as SIG_INT) the signal handler function is called, so a warning is displayed and the program execution continues. When the user presses Ctrl + C again, now the program terminates. What happened? Why did it terminate?

Every signal has a default signal handler function which is called when you dont provide a user defined signal handler function. But here we have provided our signal handler then whats the problem? well, once the signal handler function is called, the pointer to the signal handler function is actually reset to the default signal handler function. So how to overcome this problem? This is simple. In your signal handler function, again set the signal handler back to the user defined signal handler function.

void sig_int_handler(int sig)
signal (SIGINT, sig_int_handler);
//your code goes here.

once a signal appears, the signal handler is called and the signal handler pointer is reset to default signal handler. Now the control comes to the signal handler function, here we are saying that the signal handler for SIG_INT is sig_int_handler. So we are again setting the signal handler function. This avoids the termination of program when Ctrl + C is pressed two time or more.

One concern here is if the signals occur at a rate faster than the time taken for the process to enter the signal handler function and reset the signal handler pointer back to the user defined signal handler function, then the program may actually call the default signal handler and terminate!!!

Saturday, February 04, 2006

Puzzles to puzzle you!!

Q1) There are five houses in a row, each of different color, and inhabited by five different people of different nationalities, with different pets, favorite drinks and favorite sports. Use the clues below to determine who owns the monkey and who drinks water.

1. The Englishman lives in the red house.
2. The Spaniard owns the dog.
3. Coffee is drunk in the green house.
4. The Russian drinks tea.
5. The green house is immediately to the right of white house.
6. The hockey player owns hamsters.
7. The football player lives in the yellow house.
8. Milk is drunk in the middle house.
9. The American lives in the first house to the left.
10. The table tennis player lives in the house next to the man with the fox.
11. The football player lives next to the house where the horse is kept.
12. The basketball player drinks orange juice.
13. The Japanese likes baseball.
14. The American lives next to the blue house.

Q2) Ten students, sitting in 2 rows of 5 each, took their 500-point final exam in advanced calculus. The students’ scores were all multiples of ten with no two of then receiving the same score. Use the following clues and the professor’s seating chart below to determine which student sat in which seats and the test score each student earned.

1. Hugh sat next to both Ida and to the student making 82%, which was the lowest grade on the test.
2. George and the student scoring 470 sat in diagonally opposite corner seats.
3. Chuck sat somewhere between Bill and the student scoring 410, although these 3 students are not necessarily in the same row. Similarly, Ann sat somewhere between Eve and the student scoring 490.
4. The sum of the scores of the students sitting in the first column is 880.
5. Jerry’s score was 10 points better than Dolly’s but 50 points less than Frank’s.
6. The average score of those in the Column 2 is the same as that of those in Column 4, but is 5 points less than the average of those in Column 3.
7. The student with the lowest score of those in the first row sat directly in the front of the student with the highest score of those in the second row.
8. The average test score of those in the first row is 46 points higher than the average of those in the second row.