Section 4.10. Signals


4.10. Signals

Signals are used to notify a process or thread of a particular event. When the signal is received, that signal is handled through either a default mechanism or a signal handler. POSIX defines a set of signals and signal handling functions that are implemented in Linux. Linux supports both POSIX standard signals and POSIX real-time signals. This section compares and contrasts signal support between Linux 2.6 and Solaris.

4.10.1. Signal Actions

For all possible signals, the system defines a default action to take when a signal occurs:

  • Terminate. Default action is to terminate the process.

  • Ignore. Default action is to ignore the signal.

  • Core. Default action is to terminate the process and dump the core.

  • Stop. Default action is to stop the process.

A process can also install a signal handler to run when a signal is delivered to it. The signal handler takes the place of the default action associated with each signal.

Signals occur as a consequence of an event. Here are some examples that can cause a signal to be sent to a process:

  • A program error such as dividing by 0 or accessing an invalid address

  • A child process terminating

  • A timer expiring

  • A user requesting to interrupt or terminate a process

4.10.2. Simple Signals

The simplest signal-handling function Linux supports is the original ISO C standard signal() API. It allows the calling process to change the action for a particular signal to either ignore or restore the default signal action or install a function that is called when that particular signal is received by the process.

Although both Linux and Solaris support the signal() call, each implementation is different. Example 4-4 provides a sample program demonstrating both behaviors.

Example 4-4. An Example for signal( )

#include <string.h> #include <unistd.h> #include <signal.h> void handler (int signum) {   char buf[100];   strcpy (buf, "In handler\n");   buf[strlen(buf)+1] = '\0';   write (2, buf, strlen(buf)); } int main() {   signal(SIGINT, handler);   for(;;)     sleep(1);   return (0); } 

Compile and run on Linux:

# gcc signal_1.c -o signal_1 # signal_1 In handler                   <- Ctl-c In handler                   <- Ctl-c In handler                   <- Ctl-c Ctl-\ (to kill the process) Quit (core dumped) 


The BSD behavior as implemented on Linux reinstalls the signal handler when the signal is received. This is the reason why the handler is always called whenever the user presses Ctrl-C.

Compile and run on Solaris:

# cc signal_1.c -o signal_1 # ./signal_1 In handler                    <- Ctl-c <- Ctl-c #                       Program is terminated 


Traditional System V semantics of the signal() function returns the signal action to the default action when the signal is handled. Thus, a second Ctl-c sent to the process results in process termination. Solaris provides a compatibility function to the BSD signal semantics through the bsd_signal() function.

4.10.3. Signal Support in Linux

Every signal has a unique name and a corresponding signal number. Several signal numbers are architecture-dependent. The definition of signal numbers on Linux can be found in /usr/include/bits/signum.h.

To get a list of supported signals in Linux, issue a kill -l (the letter l) command.

# kill -l  1) SIGHUP        2) SIGINT         3) SIGQUIT         4) SIGILL  5) SIGTRAP       6) SIGABRT        7) SIGBUS          8) SIGFPE  9) SIGKILL       10) SIGUSR1       11) SIGSEGV        12) SIGUSR2 13) SIGPIPE       14) SIGALRM       15) SIGTERM        17) SIGCHLD 18) SIGCONT       19) SIGSTOP       20) SIGTSTP        21) SIGTTIN 22) SIGTTOU       23) SIGURG        24) SIGXCPU        25) SIGXFSZ 26) SIGVTALRM     27) SIGPROF       28) SIGWINCH       29) SIGIO 30) SIGPWR        31) SIGSYS        35) SIGRTMIN       36) SIGRTMIN+1 37) SIGRTMIN+2    38) SIGRTMIN+3    39) SIGRTMIN+4     40) SIGRTMIN+5 41) SIGRTMIN+6    42) SIGRTMIN+7    43) SIGRTMIN+8     44) SIGRTMIN+9 45) SIGRTMIN+10   46) SIGRTMIN+11   47) SIGRTMIN+12    48) SIGRTMIN+13 49) SIGRTMIN+14   50) SIGRTMAX-14   51) SIGRTMAX-13    52) SIGRTMAX-12 53) SIGRTMAX-11   54) SIGRTMAX-10   55) SIGRTMAX-9     56) SIGRTMAX-8 57) SIGRTMAX-7    58) SIGRTMAX-6    59) SIGRTMAX-5     60) SIGRTMAX-4 61) SIGRTMAX-3    62) SIGRTMAX-2    63) SIGRTMAX-1     64) SIGRTMAX 


This particular Linux implementation lists support for 30 non-real-time signals and 30 real-time signals. Table 4-16 compares signals supported by Solaris and Linux 2.6.

Table 4-16. Signal Comparison Between Solaris and Linux

Signal

Solaris Default Action

Solaris Signal Number

Linux Default Action[25]

Linux Signal Number[26]

Event

SIGHUP

Terminate

1

Terminate

1

Hangup

SIGINT

Terminate

2

Terminate

2

Interrupt

SIGQUIT

Coredump

3

Coredump

3

Quit

SIGILL

Coredump

4

Coredump

4

Illegal instruction

SIGTRAP

Coredump

5

Coredump

5

Trace or breakpoint trap

SIGABRT

Coredump

6

Coredump

6[27]

Abort

SIGEMT

Coredump

7

N/A[28]

N/A

Emulation trap

SIGFPE

Coredump

8

Coredump

8

Arithmetic exception

SIGKILL

Terminate

9

Terminate

9

Killed

SIGBUS

Coredump

10

Coredump

7

Bus error

SIGSEGV

Coredump

11

Coredump

11

Segmentation fault

SIGSYS

Coredump

12

Coredump

31

Bad system call

SIGPIPE

Terminate

13

Terminate

13

Broken pipe

SIGALRM

Terminate

14

Terminate

14

Alarm clock

SIGTERM

Terminate

15

Terminate

15

Terminated

SIGUSR1

Terminate

16

Terminate

10

User signal 1

SIGUSR2

Terminate

17

Terminate

12

User signal 2

SIGCHLD

Ignore

18

Ignore

17

Child status changed

SIGPWR

Ignore

19

Terminate

30

Power fail or restart

SIGWINCH

Ignore

20

Ignore

28

Window size change

SIGURG

Ignore

21

Ignore

23

Urgent socket condition

SIGPOLL

Terminate

22

Terminate

29[29]

Pollable event

SIGSTOP

Stop

23

Stop

19

Stopped (signal)

SIGTSTP

Stop

24

Stop

20

Stopped (user)

SIGCONT

Ignore

25

Ignore

18

Continued

SIGTTIN

Stop

26

Stop

21

Stopped (tty input)

SIGTTOU

Stop

27

Stop

22

Stopped (tty output)

SIGVTALRM

Terminate

28

Terminate

26

Virtual timer expired

SIGPROF

Terminate

29

Terminate

27

Profiling timer expired

SIGXCPU

Coredump

30

Coredump

24

CPU time limit exceeded

SIGXFSZ

Coredump

31

Coredump

25

File size limit exceeded

SIGWAITING

Ignore

32

N/A

N/A

Reserved for threading support

SIGLWP

Ignore

33

N/A

N/A

Reserved for threading support

SIGFREEZE

Ignore

34

N/A

N/A

Checkpoint freeze

SIGTHAW

Ignore

35

N/A

N/A

Checkpoint thaw

SIGCANCEL

Ignore

36

N/A

N/A

Reserved for threading support

SIGLOST

Terminate

37

N/A

N/A

Resource lost

SIGXRES

Ignore

38

N/A

N/A

Resource control exceeded

SIGJVM1

Ignore

39

N/A

N/A

Reserved for Java Virtual Machine 1

SIGJVM2

Ignore

40

N/A

N/A

Reserved for Java Virtual Machine 2

SIGRTMIN

Terminate

*

Terminate

34

First real-time signal

(SIGRTMIN+1)

Terminate

*

Terminate

*

Second real-time signal

. . .

     

(SIGRTMAX-1)

Terminate

*

Terminate

*

Second-to-last real-time signal

SIGRTMAX

Terminate

*

Terminate

64

Last real-time signal

SIGSTKFLT

N/A

N/A

Terminate

16

Stack fault on coprocessor (unused)


[25] This was taken from the comment section in linux/kernel/signal.c version 2.6.10.

[26] Signal numbers are for the Linux/i386 architecture.

[27] In Linux, SIGABRT and SIGIOT are identical.

[28] Not available in Linux/i386, but it is in Linux/Sparc, alpha, and mips.

[29] In Linux, SIGPOLL and SIGIO are identical.

4.10.4. POSIX Signal-Catching Function

Linux provides the POSIX signal-handling API sigaction(). Here is sigaction as defined by the POSIX standard:

#include <signal.h> int sigaction(int sig, const struct sigaction *restrict act,     struct sigaction *restrict oact); 


The sigaction structure defined in signal.h follows the POSIX definition, as follows:

typedef struct {       void (*sa_handler)(int);   /* Pointer to a signal-catching                  * function or one of the macros.                                     * SIG_IGN or SIG_DFL.                                     */       sigset_t sa_mask;     /* Set of signals to be blocked                * during execution of the signal                * handling function.                */    int sa_flags;      /* Special flags.                */    void (*sa_sigaction)(int, siginfo_t *, void *);                /* Pointer to a signal-catching                 * function.                 */ } sigaction_t; 


The definition of the sa_sigaction function pointer within the sigaction_t structure uses an argument that is of type siginfo_t, which is a structure that can be used to get more information about the signal's context. Here is a simplified version of the siginfo_t structure as defined in bits/siginfo.h in Linux:

typedef struct {     int  si_signo;    /* Signal number.  */     int  si_errno;    /* If non-zero, an errno value is associated             * with this signal, as defined in <errno.h>.             */     int  si_code;     /* Signal code.   */     pid_t si_pid;     /* Sending process ID. */     uid_t si_uid ;    /* Real user ID of sending              * process.              */     sigval si_value;  /* Signal value.    */ } siginfo_t; 


4.10.5. Signal Sets

The data type sigset_t in Solaris is defined differently from that in Linux.

In Linux, /usr/include/bits/sigset.h:

# define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int))) typedef struct  {   unsigned long int __val[_SIGSET_NWORDS];  } __sigset_t; 


In Solaris, /usr/include/sys/signal.h:

typedef struct {       /* signal set type */     unsigned int __sigbits[4]; } sigset_t; 


sigset_t is used in many POSIX signal-handling interfaces such as sigemptyset, sigfillset, sigaddset, sigdelset, sigismember, and sigprocmask.

4.10.6. Signal Information

Information about how and why a signal was generated is called the signal's context or information. Within the siginfo_t structure, the following members, si_signo and si_code, can be used to obtain more information about the signal. For examples of how to use siginfo_t, refer to the code in Linux Application Development, by Johnson and Troan, and Linux Programming by Example, by Robbins.

The Linux and Solaris implementations of the si_signo and si_code values are quite close. The only exception is for those signals only supported by Solaris, such as SIGXRES. Table 4-17 shows the available si_code values.

Table 4-17. Values of si_code as Implemented in Linux 2.6 and Solaris 10

Signal

Solaris si_code[30]

Linux si_code[31]

Description

SIGILL

ILL_ILLOPC

ILL_ILLOPC

Illegal opcode

 

ILL_ILLOPN

ILL_ILLOPN

Illegal operand

 

ILL_ILLADR

ILL_ILLADR

Illegal addressing mode

 

ILL_ILLTRP

ILL_ILLTRP

Illegal trap

 

ILL_PRVOPC

ILL_PRVOPC

Privileged opcode

 

ILL_PRVREG

ILL_PRVREG

Privileged register

 

ILL_COPROC

ILL_COPROC

Coprocessor error

 

ILL_BADSTK

ILL_BADSTK

Internal stack error

SIGFPE

FPE_INTDIV

FPE_INTDIV

Integer divided by 0

 

FPE_INTOVF

FPE_INTOVF

Integer overflow

 

FPE_FLTDIV

FPE_FLTDIV

Floating-point divided by 0

 

FPE_FLTOVF

FPE_FLTOVF

Floating-point overflow

 

FPE_FLTUND

FPE_FLTUND

Floating-point underflow

 

FPE_FLTRES

FPE_FLTRES

Invalid floating-point operation

 

FPE_FLTINV

FPE_FLTINV

Invalid floating-point operation

 

FPE_FLTSUB

FPE_FLTSUB

Subscript out of range

 

FPE_FLTDEN

N/A

Floating-point denormalize

SIGSEGV

SEGV_MAPERR

SEGV_MAPERR

Address not mapped to object

 

SEGV_ACCERR

SEGV_ACCERR

Invalid permissions for mapped object

SIGBUS

BUS_ADRALN

BUS_ADRALN

Invalid address alignment

 

BUS_ADRERR

BUS_ADRERR

Nonexistent physical address

 

BUS_OBJERR

BUS_OBJERR

Object-specific hardware error

SIGTRAP

TRAP_BRKPT

trAP_BRKPT

Process breakpoint

 

trAP_TRACE

trAP_TRACE

Process trace trap

 

trAP_RWATCH

N/A

Read access watchpoint trap

 

trAP_WWATCH

N/A

Write access watchpoint trap

 

trAP_XWATCH

N/A

Execute access watchpoint trap

 

trAP_DTRACE

N/A

Problem with fasttrap DTrace provider

SIGCHLD

CLD_EXITED

CLD_EXITED

Child exited

 

CLD_KILLED

CLD_KILLED

Child killed

 

CLD_DUMPED

CLD_DUMPED

Child terminated abnormally

 

CLD_TRAPPED

CLD_TRAPPED

Traced Child trapped

 

CLD_STOPPED

CLD_STOPPED

Child stopped

 

CLD_CONTINUED

CLD_CONTINUED

Stopped child continued

SIGPOLL

POLL_IN

POLL_IN

Data input available

 

POLL_OUT

POLL_OUT

Output buffers available

 

POLL_MSG

POLL_MSG

Input message available

 

POLL_ERR

POLL_ERR

I/O error

 

POLL_PRI

POLL_PRI

High-priority input available

 

POLL_HUP

POLL_HUP

Device disconnected

SIGEMT

EMT_CPCOVF

N/A

CPU performance counter overflow

SIGXRES

SI_RCTL

N/A

Resource control generated signal


[30] From /usr/include/sys/siginfo.h in Solaris

[31] From /usr/include/bits/siginfo.h in Linux

4.10.7. kill()

kill() is a traditional UNIX function for sending a signal:

int kill(pid_t pid, int sig) 


There is a slight difference between Solaris and Linux when the first argument pid is equal to 1. On a Linux system, the specified signal is sent to every process except the init process (PID 1). On a Solaris system, the signal is sent to all processes except the init process and other special processes.




UNIX to Linux Porting. A Comprehensive Reference
UNIX to Linux Porting: A Comprehensive Reference
ISBN: 0131871099
EAN: 2147483647
Year: 2004
Pages: 175

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net