How can I verify whether a running process will catch a signal, or ignore it, or block it? Ideally I'd like to see a list of signals, or at least not have to actually send the signal to check.
Process – How to Check Signals a Process is Listening To
processsignals
Related Solutions
In addition to processes calling kill(2)
, some signals are sent by the kernel (or sometimes by the process itself) in various circumstances:
- Terminal drivers send signals corresponding to various events:
- Key press notifications:
SIGINT
(please go back to the main loop) on Ctrl+C,SIGQUIT
(please quit immediately) on Ctrl+\,SIGTSTP
(please suspend) on Ctrl+Z. The keys can be changed with thestty
command. SIGTTIN
andSIGTTOU
are sent when a background process tries to read or write to its controlling terminal.SIGWINCH
is sent to signal that the size of the terminal window has changed.SIGHUP
is sent to signal that the terminal has disappeared (historically because your modem had hung up, nowadays usually because you've closed the terminal emulator window).
- Key press notifications:
- Some processor traps can generate a signal. The details are architecture and system dependent; here are typical examples:
- A number of signals notify the target process that some system event has occured:
SIGALRM
notifies that a timer set by the process has expired. Timers can be set withalarm
,setitimer
and others.SIGCHLD
notifies a process that one of its children has died.SIGPIPE
is generated when a process tries to write to a pipe when the reading end has been closed (the idea is that if you runfoo | bar
andbar
exits,foo
gets killed by aSIGPIPE
).SIGPOLL
(also calledSIGIO
) notifies the process that a pollable event has occured. POSIX specifies pollable events registered through theI_SETSIG
ioctl
. Many systems allow pollable events on any file descriptor, set via theO_ASYNC
fcntl
flag. A related signal isSIGURG
, which notifies of urgent data on a device (registered via theI_SETSIG
ioctl
) or socket.- On some systems,
SIGPWR
is sent to all processes when the UPS signals that a power failure is imminent.
These lists are not exhaustive. Standard signals are defined in signal.h
.
Most signals can be caught and handled (or ignored) by the application. The only two portable signals that cannot be caught are SIGKILL
(just die) and STOP
(stop execution).
SIGSEGV
(segmentation fault) and its cousin SIGBUS
(bus error) can be caught, but it's a bad idea unless you really know what you're doing. A common application for catching them is printing a stack trace or other debug information. A more advanced application is to implement some kind of in-process memory management, or to trap bad instructions in virtual machine engines.
Finally, let me mention something that isn't a signal. When you press Ctrl+D at the beginning of a line in a program that's reading input from the terminal, this tells the program that the end of the input file is reached. This isn't a signal: it's transmitted via the input/output API. Like Ctrl+C and friends, the key can be configured with stty
.
Recent versions of the nVidia proprietary drivers (possibly combined with other recent versions of libraries) have a bug which causes them to corrupt the signal mask.
You can look at signal masks like this:
anthony@Zia:~$ ps -eo blocked,pid,cmd | egrep -v '^0+ '
BLOCKED PID CMD
fffffffe7ffbfeff 605 udevd --daemon
0000000000000002 4052 /usr/lib/policykit-1/polkitd --no-debug
0000000000087007 4646 /usr/sbin/mysqld --basedir=/usr […]
0000000000010000 15508 bash
That's about what it should look like. If you run that on a system with the proprietary nVidia drivers, you'll see all kinds of crazy values for BLOCKED
, for many of your programs—including, likely, all the misbehaving ones.
Note that signal masks are passed from parent to child through fork
/exec
, so once a parent process has a corrupt one, all the children it spawns from that point forward will, too.
See also my question After upgrade, X button in titlebar no longer closes xterm and various distro bugs you'll be able to find now, knowing which package to look at. You can modify the code in my answer to that question to reset the signal mask to none blocked (Elide sigaddset
and change SIG_UNBLOCK
to SIG_SETMASK
).
Best Answer
Under Linux, you can find the PID of your process, then look at
/proc/$PID/status
. It contains lines describing which signals are blocked (SigBlk), ignored (SigIgn), or caught (SigCgt).The number to the right is a bitmask. If you convert it from hex to binary, each 1-bit represents a caught signal, counting from right to left starting with 1. So by interpreting the SigCgt line, we can see that my
init
process is catching the following signals:(I found the number-to-name mapping by running
kill -l
from bash.)EDIT: And by popular demand, a script, in POSIX sh.