Each signal has a current disposition, which determines how the process behaves when it is delivered the signal.
A process can change the disposition of a signal using sigaction or signal.
(avoid using signal(). because signal() varies across UNIX versions, and has also varied historically across different versions of Linux. But signal() is easy to use and simple. so It'd be better to be aware of it.)
The signal() sets the disposition of the signal signum to handler, which is either SIG_IGN, SIG_DFL, or the address of a programmer-defined function (a "signal handler").
#include <signal.h>
sighandler_t signal(int signum, sighandler_t handler);
typedef void (*sighandler_t)(int);
programmer-defined function(signal handler) is needed to be made with proper format. signal handler is given the int type parameter and returns void * type.
Example
: if SIGINT occurs, then signal_handler is called with argument signum.
void signal_handler(int signum);
...
signal(SIGINT, signal_handler);
The sigaction() system call is used to change the action taken by a process on receipt of a specific signal.
#include <signal.h>
int sigaction(int signum, const struct sigaction *restrict act, struct sigaction *restrict oldact);
Parameters
struct sigaction
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_handler specifies the action to be associated with signum. (It could be SIG_DFL, SIG_IGN either or address of function you defined.)
sa_sigaction (using If SA_SIGINFO is specified in sa_flags. instead of sa_handler.) specifies the signal-handling function for signum.
sa_mask specifies a mask of signals which should be blocked during execution of the signal handler.
sa_flags specifies a set of flags which modify the behavior of the signal. (see the manual if there is some option you need.)
The siginfo_t argument to a SA_SIGINFO handler
When the SA_SIGINFO flag is specified in act.sa_flags, the signal handler address is passed via the act.sa_sigaction field.
void
handler(int sig, siginfo_t info, void ucontext)
{
...
}
info
: A pointer to a siginfo_t, which is a structure containing further information about the signal.
ucontext
: This is a pointer to a ucontext_t structure, cast to void *. The structure pointed to by this field contains signal context information that was saved on the user-space stack by the kernel; for details, see sigreturn(2).
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 */
union sigval 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 Linux 2.6.32) */
void *si_lower; /* Lower bound when address violation
occurred (since Linux 3.19) */
void *si_upper; /* Upper bound when address violation
occurred (since Linux 3.19) */
int si_pkey; /* Protection key on PTE that caused
fault (since Linux 4.6) */
void *si_call_addr; /* Address of system call instruction
(since Linux 3.5) */
int si_syscall; /* Number of attempted system call
(since Linux 3.5) */
unsigned int si_arch; /* Architecture of attempted system call
(since Linux 3.5) */
}
Example
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
void
handler(int signo, siginfo_t *info, void *context)
{
struct sigaction oldact;
if (sigaction(SIGSEGV, NULL, &oldact) == -1 ||
(oldact.sa_flags & SA_UNSUPPORTED) ||
!(oldact.sa_flags & SA_EXPOSE_TAGBITS)) {
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
int
main(void)
{
struct sigaction act = { 0 };
act.sa_flags = SA_SIGINFO | SA_UNSUPPORTED | SA_EXPOSE_TAGBITS;
act.sa_sigaction = &handler;
if (sigaction(SIGSEGV, &act, NULL) == -1) {
perror("sigaction");
exit(EXIT_FAILURE);
}
raise(SIGSEGV);
}