DIY Signal Handler by Sigaction

In Linux environment, a program is capable of listening and generating signals. A signal is used to inform that an event happened, and it needs attention.The list of signals can be found here. The most simplest example to this is SIGINT, interrupt signal. This signal is sent when you press to quit your program you ran in a terminal. Terminating the program is SIGINT’s default signal handler. This signal handler can be overridden. In the previous post, I showed you an example how to change it to your version by using sigaction function.

In this post I’m going to instruct how to use it.

Assign a Handler


#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

First thing first, before starting signal programming, it is necessary to include .

Sigaction defines an action when a program receives a signal. It takes 3 arguments:

  1. signum – which signal to be defined
  2. act – a new signal handler struct
  3. oldact – passed to save the previous signal handler struct

Define a Handler

The type name of the signal handler struct is struct sigaction. Be sure to type the word “struct” every time we refer to this data type.

Struct sigaction is defined as


struct sigaction {
    void     (*sa_handler)(int);
    void     (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t   sa_mask;
    int        sa_flags;
    void     (*sa_restorer)(void);
};

sa_sigaction is the signal handler. It takes 3 arguments: a signal number, a signal information and a user context, respectively. You can use these 2nd and 3rd arguments to make your signal handlers smarter.

This is the struct for siginfo_t

siginfo_t {
    int      si_signo;    /* Signal number */
    int      si_errno;    /* An errno value */
    int      si_code;     /* Signal code */
    int      si_trapno;   /* Trap number that caused
                             hardware-generated signal
                             (unused on most architectures) */
    pid_t    si_pid;      /* Sending process ID */
    uid_t    si_uid;      /* Real user ID of sending process */
    int      si_status;   /* Exit value or signal */
    clock_t  si_utime;    /* User time consumed */
    clock_t  si_stime;    /* System time consumed */
    sigval_t si_value;    /* Signal value */
    int      si_int;      /* POSIX.1b signal */
    void    *si_ptr;      /* POSIX.1b signal */
    int      si_overrun;  /* Timer overrun count; POSIX.1b timers */
    int      si_timerid;  /* Timer ID; POSIX.1b timers */
    void    *si_addr;     /* Memory location which caused fault */
    long     si_band;     /* Band event (was int in
                             glibc 2.3.2 and earlier) */
    int      si_fd;       /* File descriptor */
    short    si_addr_lsb; /* Least significant bit of address
                             (since kernel 2.6.32) */
}

and this is the struct for ucontext

struct ucontext {
    unsigned long      uc_flags;
    struct ucontext  *uc_link;
    stack_t          uc_stack;
    struct sigcontext uc_mcontext;
    sigset_t      uc_sigmask;    /* mask last for extensibility */
};

Note that these are generic version of themselves. Each architecture may have its own version.

sa_handler is the fall-back signal handler in case of sa_sigaction is not defined. It takes only 1 argument, a signal number. It can be set to 3 values:

  1. SIG_DFL – a default signal handler
  2. SIG_IGN – ignore this signal
  3. Your function

sa_mask defines a signal block mask. Other signals may be raised during a signal handler is operating. This mask blocks other signals to start their handlers. The blocked signals start as soon as the previous handler finished.

sa_flags sets attributes for signal handling. Go to this link and scroll down a little until you see flags starting with SA_.

According to the man page, it says SA_SIGINFO must be set to use sa_sigaction, but so far as I tested. sa_sigaction doesn’t need it. Please check it on your machine.

Invoke the Handler

Signals can be generated in many ways, but to raise it manually you can do either of these:

And … that’s all for this post. Now you can experiment with signals in Linux by yourself. Have fun coding.

Advertisements

One thought on “DIY Signal Handler by Sigaction

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