Thursday, August 21, 2008

sigaction() - Handle a signal being a system programmer.

sigaction( ) - Sigaction provides a robust signal handling interface. It offers a lot more granularity, ability to customize and control and hence is the preferred interface now- a-days.

At the heart of sigaction is a structure struct sigaction containing atleast the following elements.

void (*) (int) sa_handler /* function, SIG_DFL or SIG_IGN
sigset_t sa_mask /* signals to block in sa_handler
int sa_flags /* signal action modifiers

To handle signals using sigaction( ), it's a two step process.
Step 1 - Populate the sigaction structure.
Have your sa_handler assigned to the signal hander function name.
Mostly you'd set sa_flags to Null. I've not used them.
sa_mask is for blocking any signal in the sa_handler. The important thing about using it is that once signal handling is done, You have to reset it. By default it doesn't get reset.
sigemptyset ( ) is a helper function that You can use to initialize it to block no signals.

Step 2 - Register the signal handling details with sigaction.

Basically, in sigaction ( ), You pass three parameters.
Param-1 : int signal_number
Param-2 : const struct *act : This is the pointer which should point to the above populated structure. When a signal arrives, first the signal mask provided in the act structure would be set, then the signal handler function gets called.
Param-3 : struct *oact :The signal hadling action of the last signal caught is populated in it.
I've kept this parameter NULL. Mostly You'll also keep it NULL.

We are basically done with sigaction. However, there are some notable details.
sa_flags : There are some important flags -
SA_RESTART - If a system call or function has stopped due to arrival of the signal, after signal handling is over, the function will be restarted rather than returning with error EINTR.
SA_RESETHAND - Once the signal is caught, the default behaviour of the signal will be restored. i.e. the signal handler registered will be cleared.

SA_NODEFER- Don't add the signal to the signal mask while handling it. Generally, when a signal is getting serviced, the signal would be added to the signal mask so that the signal handling in the middle of execution is not corrupted. However, if You want this behaviour to change and say, your handler to be capable of serving parallel signals at the same time, then use this mask. However, to achieve it, the signal handling code has to be re-entrant.

An important element of Signal handling is using the Signal Sets.
They are used to define the behaviour of a process on receipt of a signal.

sigemptyset( ) - Initialize the signal set to be empty.
sigismember( ) - Find out whether a particular signal is part of the signal set.
sigaddset( ) - Add signal to the set.
sigdelset( ) - Delete the signal from the set.
sigfillset( ) - Fill the set with all the signals.
sigprocmask() - For the signal mentioned, the signal mask is set and the old mask is written.



Well, this completes the signal hadling.

No comments: