10.14. sigaction FunctionThe sigaction function allows us to examine or modify (or both) the action associated with a particular signal. This function supersedes the signal function from earlier releases of the UNIX System. Indeed, at the end of this section, we show an implementation of signal using sigaction.[View full width]#include <signal.h> int sigaction(int signo , const struct sigaction ![]() struct sigaction *restrict oact ); |
Returns: 0 if OK, 1 on error |
void (*sa_handler)(int); /* addr of signal handler, */
/* or SIG_IGN, or SIG_DFL */
sigset_t sa_mask; /* additional signals to block */
int sa_flags; /* signal options, Figure 10.16 */
/* alternate handler */
void (*sa_sigaction)(int, siginfo_t *, void *);
};
Section 10.8 that additional occurrences of the same signal are usually not queued. If the signal occurs five times while it is blocked, when we unblock the signal, the signal-handling function for that signal will usually be invoked only one time.Once we install an action for a given signal, that action remains installed until we explicitly change it by calling sigaction. Unlike earlier systems with their unreliable signals, POSIX.1 requires that a signal handler remain installed until explicitly changed.The sa_flags field of the act structure specifies various options for the handling of this signal. Section 10.5 for more information.
but if the SA_SIGINFO flag is set, the signal handler is called asvoid handler(int signo , siginfo_t *info , void *context );
The siginfo_t structure contains information about why the signal was generated. An example of what it might look like is shown below. All POSIX.1-compliant implementations must include at least the si_signo and si_code members. Additionally, implementations that are XSI compliant contain at least the following fields:struct siginfo {
int si_signo; /* signal number */
int si_errno; /* if nonzero, errno value from <errno.h> */
int si_code; /* additional info (depends on signal) */
pid_t si_pid; /* sending process ID */
uid_t si_uid; /* sending process real user ID */
void *si_addr; /* address that caused the fault */
int si_status; /* exit value or signal number */
long si_band; /* band number for SIGPOLL */
/* possibly other fields also */
};
Figure 10.17 shows values of si_code for various signals, as defined by the Single UNIX Specification. Note that implementations may define additional code values.
Signal | Code | Reason |
---|---|---|
ILL_ILLOPC | illegal opcode | |
ILL_ILLOPN | illegal operand | |
ILL_ILLADR | illegal addressing mode | |
SIGILL | ILL_ILLTRP | illegal trap |
ILL_PRVOPC | privileged opcode | |
ILL_PRVREG | privileged register | |
ILL_COPROC | coprocessor error | |
ILL_BADSTK | internal stack error | |
FPE_INTDIV | integer divide by zero | |
FPE_INTOVF | integer overflow | |
FPE_FLTDIV | floating-point divide by zero | |
FPE_FLTOVF | floating-point overflow | |
SIGFPE | FPE_FLTUND | floating-point underflow |
FPE_FLTRES | floating-point inexact result | |
FPE_FLTINV | invalid floating-point operation | |
FPE_FLTSUB | subscript out of range | |
SIGSEGV | SEGV_MAPERR | address not mapped to object |
SEGV_ACCERR | invalid permissions for mapped object | |
BUS_ADRALN | invalid address alignment | |
SIGBUS | BUS_ADRERR | nonexistent physical address |
BUS_OBJERR | object-specific hardware error | |
trAP_BRKPT | process breakpoint trap | |
SIGTRAP | TRAP_TRACE | process trace trap |
CLD_EXITED | child has exited | |
CLD_KILLED | child has terminated abnormally (no core) | |
CLD_DUMPED | child has terminated abnormally with core | |
SIGCHLD | CLD_TRAPPED | traced child has trapped |
CLD_STOPPED | child has stopped | |
CLD_CONTINUED | stopped child has continued | |
POLL_IN | data can be read | |
POLL_OUT | data can be written | |
SIGPOLL | POLL_MSG | input message available |
POLL_ERR | I/O error | |
POLL_PRI | high-priority message available | |
POLL_HUP | device disconnected | |
SI_USER | signal sent by kill | |
SI_QUEUE | signal sent by sigqueue (real-time extension) | |
Any | SI_TIMER | expiration of a timer set by timer_settime (real-time extension) |
SI_ASYNCIO | completion of asynchronous I/O request (real-time extension) | |
SI_MESGQ | arrival of a message on a message queue (real-time extension) |
Examplesignal Function
Let's now implement the signal function using sigaction. This is what many platforms do (and what a note in the POSIX.1 Rationale states was the intent of POSIX). Systems with binary compatibility constraints, on the other hand, might provide a signal function that supports the older, unreliable-signal semantics. Unless you specifically require these older, unreliable semantics (for backward compatibility), you should use the following implementation of signal or call sigaction directly. (As you might guess, an implementation of signal with the old semantics could call sigaction specifying SA_RESETHAND and SA_NODEFER.) All the examples in this text that call signal call the function shown in Figure 10.18.Note that we must use sigemptyset to initialize the sa_mask member of the structure. We're not guaranteed thatact.sa_mask = 0;
does the same thing.We intentionally try to set the SA_RESTART flag for all signals other than SIGALRM, so that any system call interrupted by these other signals is automatically restarted. The reason we don't want SIGALRM restarted is to allow us to set a timeout for I/O operations. (Recall the discussion of Figure 10.10.)Some older systems, such as SunOS, define the SA_INTERRUPT flag. These systems restart interrupted system calls by default, so specifying this flag causes system calls to be interrupted. Linux defines the SA_INTERRUPT flag for compatibility with applications that use it, but the default is to not restart system calls when the signal handler is installed with sigaction. The XSI extension of the Single UNIX Specification specifies that the sigaction function not restart interrupted system calls unless the SA_RESTART flag is specified.
Figure 10.18. An implementation of signal using sigaction
#include "apue.h"
/* Reliable version of signal(), using POSIX sigaction(). */
Sigfunc *
signal(int signo, Sigfunc *func)
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo == SIGALRM) {
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
} else {
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART;
#endif
}
if (sigaction(signo, &act, &oact) < 0)
return(SIG_ERR);
return(oact.sa_handler);
}
Examplesignal_intr Function
Figure 10.19 shows a version of the signal function that tries to prevent any interrupted system calls from being restarted.For improved portability, we specify the SA_INTERRUPT flag, if defined by the system, to prevent interrupted system calls from being restarted.
Figure 10.19. The signal_intr function
#include "apue.h"
Sigfunc *
signal_intr(int signo, Sigfunc *func)
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
if (sigaction(signo, &act, &oact) < 0)
return(SIG_ERR);
return(oact.sa_handler);
}
