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).
# cat /proc/1/status
...
SigBlk: 0000000000000000
SigIgn: fffffffe57f0d8fc
SigCgt: 00000000280b2603
...
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:
00000000280b2603 ==> 101000000010110010011000000011
| | | || | || |`-> 1 = SIGHUP
| | | || | || `--> 2 = SIGINT
| | | || | |`----------> 10 = SIGUSR1
| | | || | `-----------> 11 = SIGSEGV
| | | || `--------------> 14 = SIGALRM
| | | |`-----------------> 17 = SIGCHLD
| | | `------------------> 18 = SIGCONT
| | `--------------------> 20 = SIGTSTP
| `----------------------------> 28 = SIGWINCH
`------------------------------> 30 = SIGPWR
(I found the number-to-name mapping by running kill -l
from bash.)
EDIT: And by popular demand, a script, in POSIX sh.
sigparse () {
i=0
# bits="$(printf "16i 2o %X p" "0x$1" | dc)" # variant for busybox
bits="$(printf "ibase=16; obase=2; %X\n" "0x$1" | bc)"
while [ -n "$bits" ] ; do
i="$(expr "$i" + 1)"
case "$bits" in
*1) printf " %s(%s)" "$(kill -l "$i")" "$i" ;;
esac
bits="${bits%?}"
done
}
grep "^Sig...:" "/proc/$1/status" | while read a b ; do
printf "%s%s\n" "$a" "$(sigparse "$b")"
done # | fmt -t # uncomment for pretty-printing
Could anybody please tell me the reason to why pending signals are not inherited by the child process?
Signals come in two flavours, synchronous and asynchronous. Synchronous ones begin with the kernel in response to something the process did -- e.g., the ever popular SIGSEGV. Asynchronous signals generally come from other processes, and, as the name implies, arrive at some arbitrary point. A "pending" signal is either one which simply hasn't been delivered yet, or one which has been blocked temporarily by the receiving process. Consider some pending scenarios and why it would be inappropriate for the child to inherit them.
Synchronous, undelivered: Let's take the example of a SIGSEGV that's pending because the parent committed an access violation -- something I'm sure actually doesn't happen or doesn't happen for long enough to really consider it as "pending" from a userspace perspective, but for sake of argument -- then it's the parent that committed the violation, not the child. If the child then proceeds to do something similar (which it likely would), it will get its own signal anyway. If by chance it doesn't, then it shouldn't receive one that was pending for the parent.
Asynchronous, undelivered: In this case, it really cannot be meaningful if the signal was pending for the duration of the fork and then delivered to the parent, since the signal is asynchronous -- it cannot be intended to interrupt the process at a particular point, it's like a phone call; the caller isn't intending to catch you while you are still sitting in your chair because the caller can't know that. The point of the call is just to communicate something to you. Further, signals are addressed to specific process, and the child is a separate process with its own PID. If I send a signal to process 1001, I do not expect it to also go to process 1002.
Blocked (synchronous or asynchronous): In this case, the signal is left pending intentionally by the process, so it had the opportunity to unblock it before the fork (but didn't). Since it is known that such signals will not be inherited by the child, this scenario occurs by design. For example, a server receives a signal and for what ever reason decides to block it temporarily while it answers an incoming request -- pselect()
will accomplish this, I think -- and to handle the request it forks a child. Then it deals with the pending signal.
On the other hand, the child process inherits the signal handlers and signal mask from the parent, why is this done?
That seems integral to the concept of a fork: the child is a copy of the parent. Signal handlers are just regular functions with a special purpose. Again, since this is known it can be exploited by design, or conversely, compensated for. It is easy enough to remove a handler if you no longer want to use it.
Best Answer
Well, this isn't a pretty solution, but at least it might be a solution.
In
/proc/[pid]/status
there is an entry for SigPnd and ShdPnd. They are described as,There's also SigQ which is,
(All of this is from
man 5 proc
).So you could search all the pid's in
/proc
, check theirstatus
files, and find the one with any pending signals.Try this,
cd /proc
find . -name "status" | xargs grep SigPnd 2> /dev/null | grep -v "0000000000000000"
and
find . -name "status" | xargs grep ShdPnd 2> /dev/null | grep -v "0000000000000000"