98

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.

0

9 Answers 9

143

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 
7
  • 2
    If a signal is listed under SigBlk does it also appear in SigCgt? Because by blocking it, it just means the signal will be resent a little bit later right and the needs to be caught? Commented May 29, 2015 at 7:28
  • No, you can block a signal without being ready to catch it. If you don't catch a signal, a default action will happen depending on the signal (usually process termination). If you want more detail you ought to open a question. Commented May 29, 2015 at 22:21
  • What's the use of a POSIX version of a script reading from /proc? It's only going to work on Linux... And local isn't POSIX. Well, it kinda is, but its effect is "unspecified". Commented Jan 7, 2017 at 19:42
  • 3
    @Kusalananda: Linux doesn't imply Bash -- for example, small embedded platforms often use Busybox -- but POSIX compliance is a near guarantee for any modern /bin/sh. You're right about local; I'll clean that up. Commented Jan 8, 2017 at 3:52
  • @Jander Fair point. I confess to making a hasty assumption regarding Bash and Linux. Commented Jan 8, 2017 at 8:48
24

On Solaris, run psig on the process id to get a list of signals and how they'll be handled.

For instance:

bash-4.2$ psig $$ 11088: bash HUP caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST INT caught sigint_sighandler 0 QUIT ignored ILL caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST TRAP caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST ABRT caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST EMT caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST FPE caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST KILL default BUS caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST SEGV caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST SYS caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST PIPE caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST ALRM caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST TERM ignored USR1 caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST USR2 caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST CLD blocked,caught 0x4898e8 RESTART PWR default WINCH caught sigwinch_sighandler 0 [...] 

which shows that SIGHUP, SIGILL, etc. will all be caught by the same signal handler function termsig_sighandler, which will be run without using any of the flags that could be set via sigaction, and all the signals that will be temporarily masked while the signal handler is running (in this case all the ones using the same signal handler, so it's not reentered while already running). You can also see that SIGQUIT & SIGTERM will be ignored, SIGKILL & SIGPWR use the system default signal actions, and SIGCLD specifies the RESTART flag, so if its signal handler interrupts a system call, the syscall will be restarted.

1
  • Awesome! I was hoping someone would add a non-Linux answer. Commented Aug 5, 2013 at 2:14
8

(This answer is similar to @user18096's answer, in that it creates a script around @Jander's answer.)

I've written a psig script to take a PID (or all PIDs) and create human-readable output from the signal masks in /proc/<PID>/status.

Example output:

% ./psig -a [ 1] Signals Queued: 8/773737 [ 1] Signals Pending: [ 1] Signals Pending (Shared): [ 1] Signals Blocked: [ 1] Signals Ignored: SIGPIPE [ 1] Signals Caught: SIGHUP,SIGINT,SIGABRT,SIGUSR1,SIGSEGV,SIGALRM,SIGTERM,SIGCHLD,SIGPWR ... [ 31001] Signals Queued: 0/773737 [ 31001] Signals Pending: [ 31001] Signals Pending (Shared): [ 31001] Signals Blocked: SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGTRAP,SIGABRT,SIGBUS,SIGFPE,SIGUSR1,SIGUSR2,SIGPIPE,SIGALRM,SIGTERM,SIGSTKFLT,SIGCHLD,SIGCONT,SIGTSTP,SIGTTIN,SIGTTOU,SIGURG,SIGXCPU,SIGXFSZ,SIGPROF,SIGWINCH,SIGIO,SIGPWR,SIGSYS,SIGRTMIN,SIGRTMIN+1,SIGRTMIN+2,SIGRTMIN+3,SIGRTMIN+4,SIGRTMIN+5,SIGRTMIN+6,SIGRTMIN+7,SIGRTMIN+8,SIGRTMIN+9,SIGRTMIN+10,SIGRTMIN+11,SIGRTMIN+12,SIGRTMIN+13,SIGRTMIN+14,SIGRTMIN+15,SIGRTMAX-14,SIGRTMAX-13,SIGRTMAX-12,SIGRTMAX-11,SIGRTMAX-10,SIGRTMAX-9,SIGRTMAX-8,SIGRTMAX-7,SIGRTMAX-6,SIGRTMAX-5,SIGRTMAX-4,SIGRTMAX-3,SIGRTMAX-2,SIGRTMAX-1,SIGRTMAX [ 31001] Signals Ignored: SIGHUP,SIGINT,SIGQUIT,SIGPIPE,SIGXFSZ [ 31001] Signals Caught: SIGBUS,SIGUSR1,SIGSEGV,SIGUSR2,SIGALRM,SIGTERM,SIGVTALRM 

Caveats:

  • This is a Linux specific answer.
  • Might need a relatively new Python version to run the script, it uses with and OrderedDict.
2

I keep coming back to @Jander's pretty answer hoping for a copy-and-paste decoder when faced with the like of:

user@machine:~$ grep Sig...: /proc/18475/status SigPnd: 0000000000000000 SigBlk: fffffffe7dfbfaff SigIgn: 0000000000001000 SigCgt: 0000000182006e47 user@machine:~$ 

Guess I'll have to knock something up... say:

user@machine:~$ ruby -wn - /proc/18475/status <<'EOF' if $_.match(/Sig(Pnd|Blk|Ign|Cgt):\s([0-9a-f]{16})/) == nil next end field = $1 mask = $2.to_i(16) names = [] Signal.list().each_pair() { |name, number| if number == 0 # "EXIT" => 0 next end if (mask & (1 << (number - 1))) == 0 next end names << name } puts("Sig#{field}: #{names.join(" | ")}") EOF SigPnd: SigBlk: HUP | INT | QUIT | ILL | TRAP | IOT | ABRT | FPE | BUS | SYS | PIPE | ALRM | TERM | URG | TSTP | CONT | CHLD | CLD | TTIN | TTOU | IO | XCPU | XFSZ | PROF | WINCH | USR1 | USR2 | PWR | POLL SigIgn: PIPE SigCgt: HUP | INT | QUIT | BUS | SEGV | ALRM | TERM | VTALRM | USR1 | USR2 user@machine:~$ 

I wanted it to be somewhat legible, but that's made it a bit clumsier to invoke than I'd like, so, thanks to @alanc's suggestion, I'll save it as ~/bin/psig.

2

Use this(link broken) this library to get infos about the jobs, which are running.

There is a special field in the struct Job for the signals, called sigCgt

You may use something like this:

#include"read_proc.h" int main(void) { struct Root * rt=read_proc(); struct Job * jb=rt->first->job; printf("%ull\n",jb->sigCgt); return 0; } 
2
  • I'd love to but the link is broken. Commented Jan 6, 2017 at 15:32
  • 1
    @MichaelFox see my edit. The user has deleted his account. The new link points to the same project Commented Jan 7, 2017 at 17:34
2

On FreeBSD, use procstat -i <PID> to see which signals are ignored by the process. Similarly, procstat -j <PID> to see which signals are blocked by the process threads. Both commands show if a signal is pending.

Sample output:

$ procstat -i 38540 PID COMM SIG FLAGS 38540 nsulfd HUP -I- 38540 nsulfd INT -I- 38540 nsulfd QUIT -I- 38540 nsulfd ILL --- 38540 nsulfd TRAP --- ...

$ procstat -j 38540 PID TID COMM SIG FLAGS 38540 101220 nsulfd HUP -- 38540 101220 nsulfd INT -- 38540 101220 nsulfd QUIT -B 38540 101220 nsulfd ILL -- 38540 101220 nsulfd TRAP -- ...

See procstat(1).

1

I have written a zsh function, which should be highly portable, since the only dependencies are awk and column for the fancy output:

psig()

psig() { declare -a pid_signal_array pid_signal_array[1]="SIGHUP" pid_signal_array[2]="SIGINT" pid_signal_array[3]="SIGQUIT" pid_signal_array[4]="SIGKILL" pid_signal_array[5]="SIGTRAP" pid_signal_array[6]="SIGABRT" pid_signal_array[7]="SIGBUS" pid_signal_array[8]="SIGFPE" pid_signal_array[9]="SIGKILL" pid_signal_array[10]="SIGUSR1" pid_signal_array[11]="SIGSEGV" pid_signal_array[12]="SIGUSR2" pid_signal_array[13]="SIGPIPE" pid_signal_array[14]="SIGALRM" pid_signal_array[15]="SIGTERM" pid_signal_array[16]="SIGSTKFLT" pid_signal_array[17]="SIGCHLD" pid_signal_array[18]="SIGCONT" pid_signal_array[19]="SIGSTOP" pid_signal_array[20]="SIGTSTP" pid_signal_array[21]="SIGTTIN" pid_signal_array[22]="SIGTTOU" pid_signal_array[23]="SIGURG" pid_signal_array[24]="SIGXCPU" pid_signal_array[25]="SIGXFSZ" pid_signal_array[26]="SIGVTALRM" pid_signal_array[27]="SIGPROF" pid_signal_array[28]="SIGWINCH" pid_signal_array[29]="SIGIO" pid_signal_array[30]="SIGPWR" pid_signal_array[31]="SIGSYS" # not defined #pid_signal_array[32]="" #pid_signal_array[33]="" pid_signal_array[34]="SIGRTMIN" pid_signal_array[35]="SIGRTMIN+1" pid_signal_array[36]="SIGRTMIN+2" pid_signal_array[37]="SIGRTMIN+3" pid_signal_array[38]="SIGRTMIN+4" pid_signal_array[39]="SIGRTMIN+5" pid_signal_array[40]="SIGRTMIN+6" pid_signal_array[41]="SIGRTMIN+7" pid_signal_array[42]="SIGRTMIN+8" pid_signal_array[43]="SIGRTMIN+9" pid_signal_array[44]="SIGRTMIN+10" pid_signal_array[45]="SIGRTMIN+11" pid_signal_array[46]="SIGRTMIN+12" pid_signal_array[47]="SIGRTMIN+13" pid_signal_array[48]="SIGRTMIN+14" pid_signal_array[49]="SIGRTMIN+15" pid_signal_array[50]="SIGRTMAX-14" pid_signal_array[51]="SIGRTMAX-13" pid_signal_array[52]="SIGRTMAX-12" pid_signal_array[53]="SIGRTMAX-11" pid_signal_array[54]="SIGRTMAX-10" pid_signal_array[55]="SIGRTMAX-9" pid_signal_array[56]="SIGRTMAX-8" pid_signal_array[57]="SIGRTMAX-7" pid_signal_array[58]="SIGRTMAX-6" pid_signal_array[59]="SIGRTMAX-5" pid_signal_array[60]="SIGRTMAX-4" pid_signal_array[61]="SIGRTMAX-3" pid_signal_array[62]="SIGRTMAX-2" pid_signal_array[63]="SIGRTMAX-1" pid_signal_array[64]="SIGRTMAX" declare -A hex_value_array local hex_value_array["0"]="0" local hex_value_array["1"]="1" local hex_value_array["2"]="2" local hex_value_array["3"]="3" local hex_value_array["4"]="4" local hex_value_array["5"]="5" local hex_value_array["6"]="6" local hex_value_array["7"]="7" local hex_value_array["8"]="8" local hex_value_array["9"]="9" local hex_value_array["a"]="10" local hex_value_array["b"]="11" local hex_value_array["c"]="12" local hex_value_array["d"]="13" local hex_value_array["e"]="14" local hex_value_array["f"]="15" declare -a bin_value_4bit_array=({0..1}{0..1}{0..1}{0..1}) declare -A pid_signal_name_array local pid_signal_name_array["SigPnd:"]="Signals pending (thread):" local pid_signal_name_array["ShdPnd:"]="Signals pending (process):" local pid_signal_name_array["SigBlk:"]="Signals blocked:" local pid_signal_name_array["SigIgn:"]="Signals ignored:" local pid_signal_name_array["SigCgt:"]="Signals caught:" declare -a pid_array=("${@}") for pid in "${pid_array[@]}" do local pid_directory_path="/proc/${pid}" local pid_status_file="status" local pid_status=$(< "${pid_directory_path}/${pid_status_file}") declare -a pid_signal_bin_value_4bit_array declare -a pid_signal_bin_value_1bit_array unset hex_position unset hex_value unset binary_position unset binary_value local hex_position local hex_value local binary_position local binary_value echo "" echo -n "PID: ${pid}" for pid_signal_name in "${(k)pid_signal_name_array[@]}" do local pid_signal_hex_value=$(echo "${pid_status}" | awk --assign="pid_signal_name=${pid_signal_name}" '$0 ~ pid_signal_name { print $2 }') declare -a pid_signal_hex_value_delimited_array # refactor me: create function "hexToBin()" # split hexadecimal string per character # from: 0000000180004a03 # to: 0 0 0 0 0 0 0 1 8 0 0 0 4 a 0 3 unset pid_signal_hex_value_delimited_array for hex_position in {0.."${#pid_signal_hex_value}"} do pid_signal_hex_value_delimited_array+=("${pid_signal_hex_value:${hex_position}:1}") done # convert hexadecimal to binary per character # from: 0 0 0 0 0 0 0 1 8 0 0 0 4 a 0 3 # to: 0000 0000 0000 0000 0000 0000 0000 0001 1000 0000 0000 0000 0100 1010 0000 0011 unset pid_signal_bin_value_4bit_array for hex_value in "${pid_signal_hex_value_delimited_array[@]}" do if [[ "${hex_value}" =~ ^[0-9]$ ]] then pid_signal_bin_value_4bit_array+="${bin_value_4bit_array[${hex_value}+1]} " elif [[ "${hex_value}" =~ ^[a-fA-F]$ ]] then pid_signal_bin_value_4bit_array+="${bin_value_4bit_array[hex_value_array[${hex_value}]+1]} " fi done # concatenate binary string and split string per character # from: 0000 0000 0000 0000 0000 0000 0000 0001 1000 0000 0000 0000 0100 1010 0000 0011 # to: 0000000000000000000000000000000110000000000000000100101000000011 # to: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 1 1 pid_signal_bin_value_concatenated="${pid_signal_bin_value_4bit_array[@]// /}" unset pid_signal_bin_value_1bit_array for binary_position in {0.."$(( ${#pid_signal_bin_value_concatenated} - 1 ))"} do pid_signal_bin_value_1bit_array+=("${pid_signal_bin_value_concatenated:${binary_position}:1}") done # convert binary to signal name per character # from: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 1 1 # to: Signal <signal_number>: <signal_name> local binary_array_index="${#pid_signal_bin_value_concatenated}" echo "" echo "${pid_signal_name_array[${pid_signal_name}]}" echo "${pid_signal_name_array[${pid_signal_name}]//[a-zA-Z :()]/-}" for binary_value in "${pid_signal_bin_value_1bit_array[@]}" do # signal "32" and "33" are undefined if [[ "${binary_array_index}" == "32" || "${binary_array_index}" == "33" ]] then (( binary_array_index-- )) continue elif [[ "${binary_value}" == "0" ]] then (( binary_array_index-- )) continue elif [[ "${binary_value}" == "1" ]] then echo "Signal ${binary_array_index}: ${pid_signal_array[${binary_array_index}]}" fi (( binary_array_index-- )) done # output results, if there is any signal. also output results, if signal "32" and "33" are set to "1", which actually does not make any sense. if [[ "${pid_signal_bin_value_concatenated}" == *"1"* ]] then echo -e "Hexadecimal: ${pid_signal_hex_value_delimited_array[@]}\nBinary: ${pid_signal_bin_value_4bit_array[@]}" | column --table else echo "No signals found." fi done done } 
% psig $$ SigCgt Signal 28: SIGWINCH Signal 17: SIGCHLD Signal 14: SIGALRM Signal 13: SIGPIPE Signal 2: SIGINT Signal 1: SIGHUP Hexadecimal: 0 0 0 0 0 0 0 0 0 8 0 1 3 0 0 3 Binary: 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000 0000 0001 0011 0000 0000 0011 

It is still in development and only covers SigCgt for now. I am going to port it to Bash and put it into its own repository.

I ported it to Bash and it supports all signal types: https://codeberg.org/keks24/psig

psig

#!/bin/bash ############################################################################# # Copyright 2021 Ramon Fischer # # # # Licensed under the Apache License, Version 2.0 (the "License"); # # you may not use this file except in compliance with the License. # # You may obtain a copy of the License at # # # # http://www.apache.org/licenses/LICENSE-2.0 # # # # Unless required by applicable law or agreed to in writing, software # # distributed under the License is distributed on an "AS IS" BASIS, # # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################# # define global variables declare -a pid_signal_array pid_signal_array[1]="SIGHUP" pid_signal_array[2]="SIGINT" pid_signal_array[3]="SIGQUIT" pid_signal_array[4]="SIGKILL" pid_signal_array[5]="SIGTRAP" pid_signal_array[6]="SIGABRT" pid_signal_array[7]="SIGBUS" pid_signal_array[8]="SIGFPE" pid_signal_array[9]="SIGKILL" pid_signal_array[10]="SIGUSR1" pid_signal_array[11]="SIGSEGV" pid_signal_array[12]="SIGUSR2" pid_signal_array[13]="SIGPIPE" pid_signal_array[14]="SIGALRM" pid_signal_array[15]="SIGTERM" pid_signal_array[16]="SIGSTKFLT" pid_signal_array[17]="SIGCHLD" pid_signal_array[18]="SIGCONT" pid_signal_array[19]="SIGSTOP" pid_signal_array[20]="SIGTSTP" pid_signal_array[21]="SIGTTIN" pid_signal_array[22]="SIGTTOU" pid_signal_array[23]="SIGURG" pid_signal_array[24]="SIGXCPU" pid_signal_array[25]="SIGXFSZ" pid_signal_array[26]="SIGVTALRM" pid_signal_array[27]="SIGPROF" pid_signal_array[28]="SIGWINCH" pid_signal_array[29]="SIGIO" pid_signal_array[30]="SIGPWR" pid_signal_array[31]="SIGSYS" # not defined #pid_signal_array[32]="" #pid_signal_array[33]="" pid_signal_array[34]="SIGRTMIN" pid_signal_array[35]="SIGRTMIN+1" pid_signal_array[36]="SIGRTMIN+2" pid_signal_array[37]="SIGRTMIN+3" pid_signal_array[38]="SIGRTMIN+4" pid_signal_array[39]="SIGRTMIN+5" pid_signal_array[40]="SIGRTMIN+6" pid_signal_array[41]="SIGRTMIN+7" pid_signal_array[42]="SIGRTMIN+8" pid_signal_array[43]="SIGRTMIN+9" pid_signal_array[44]="SIGRTMIN+10" pid_signal_array[45]="SIGRTMIN+11" pid_signal_array[46]="SIGRTMIN+12" pid_signal_array[47]="SIGRTMIN+13" pid_signal_array[48]="SIGRTMIN+14" pid_signal_array[49]="SIGRTMIN+15" pid_signal_array[50]="SIGRTMAX-14" pid_signal_array[51]="SIGRTMAX-13" pid_signal_array[52]="SIGRTMAX-12" pid_signal_array[53]="SIGRTMAX-11" pid_signal_array[54]="SIGRTMAX-10" pid_signal_array[55]="SIGRTMAX-9" pid_signal_array[56]="SIGRTMAX-8" pid_signal_array[57]="SIGRTMAX-7" pid_signal_array[58]="SIGRTMAX-6" pid_signal_array[59]="SIGRTMAX-5" pid_signal_array[60]="SIGRTMAX-4" pid_signal_array[61]="SIGRTMAX-3" pid_signal_array[62]="SIGRTMAX-2" pid_signal_array[63]="SIGRTMAX-1" pid_signal_array[64]="SIGRTMAX" declare -A hex_value_array hex_value_array["0"]="0" hex_value_array["1"]="1" hex_value_array["2"]="2" hex_value_array["3"]="3" hex_value_array["4"]="4" hex_value_array["5"]="5" hex_value_array["6"]="6" hex_value_array["7"]="7" hex_value_array["8"]="8" hex_value_array["9"]="9" hex_value_array["a"]="10" hex_value_array["b"]="11" hex_value_array["c"]="12" hex_value_array["d"]="13" hex_value_array["e"]="14" hex_value_array["f"]="15" # array index (decimal) points to corresponding binary value declare -a bin_value_4bit_array=({0..1}{0..1}{0..1}{0..1}) declare -A pid_signal_name_array pid_signal_name_array["SigPnd:"]="Signals pending (thread):" pid_signal_name_array["ShdPnd:"]="Signals pending (process):" pid_signal_name_array["SigBlk:"]="Signals blocked:" pid_signal_name_array["SigIgn:"]="Signals ignored:" pid_signal_name_array["SigCgt:"]="Signals caught:" underline_regex="[a-zA-Z:() ]" main() { declare -a pid_array=("${@}") for pid in "${pid_array[@]}" do local pid_directory_path="/proc/${pid}" local pid_status_file="status" local pid_status=$(< "${pid_directory_path}/${pid_status_file}") local pid_name=$(echo "${pid_status}" | /usr/bin/awk --field-separator="Name:\t" '/Name:/ { print $2 }') declare -a pid_signal_bin_value_4bit_array declare -a pid_signal_bin_value_1bit_array local hex_position local hex_value local binary_position local binary_value echo "" echo -e "PID: ${pid}" echo -n "Name: ${pid_name}" for pid_signal_name in "${!pid_signal_name_array[@]}" do local pid_signal_hex_value=$(echo "${pid_status}" | /usr/bin/awk --assign="pid_signal_name=${pid_signal_name}" '$0 ~ pid_signal_name { print $2 }') declare -a pid_signal_hex_value_delimited_array # refactor me: create function "hexToBin()" # split hexadecimal string per character # from: 0000000180004a03 # to: 0 0 0 0 0 0 0 1 8 0 0 0 4 a 0 3 unset pid_signal_hex_value_delimited_array for hex_position in $(eval echo "{0..${#pid_signal_hex_value}}") do pid_signal_hex_value_delimited_array+=("${pid_signal_hex_value:${hex_position}:1}") done # convert hexadecimal to binary per character # from: 0 0 0 0 0 0 0 1 8 0 0 0 4 a 0 3 # to: 0000 0000 0000 0000 0000 0000 0000 0001 1000 0000 0000 0000 0100 1010 0000 0011 unset pid_signal_bin_value_4bit_array for hex_value in "${pid_signal_hex_value_delimited_array[@]}" do if [[ "${hex_value}" =~ ^[0-9]$ ]] then pid_signal_bin_value_4bit_array+="${bin_value_4bit_array[${hex_value}]} " elif [[ "${hex_value}" =~ ^[a-fA-F]$ ]] then pid_signal_bin_value_4bit_array+="${bin_value_4bit_array[hex_value_array[${hex_value}]]} " fi done # concatenate binary string and split string per character # from: 0000 0000 0000 0000 0000 0000 0000 0001 1000 0000 0000 0000 0100 1010 0000 0011 # to: 0000000000000000000000000000000110000000000000000100101000000011 # to: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 1 1 pid_signal_bin_value_concatenated="${pid_signal_bin_value_4bit_array[@]// /}" unset pid_signal_bin_value_1bit_array for binary_position in $(eval echo "{0..$(( ${#pid_signal_bin_value_concatenated} ))}") do pid_signal_bin_value_1bit_array+=("${pid_signal_bin_value_concatenated:${binary_position}:1}") done # convert binary to signal name per character # from: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 1 1 # to: Signal <signal_number>: <signal_name> local binary_array_index="${#pid_signal_bin_value_concatenated}" echo "" echo "${pid_signal_name_array[${pid_signal_name}]}" echo "${pid_signal_name_array[${pid_signal_name}]//${underline_regex}/-}" for binary_value in "${pid_signal_bin_value_1bit_array[@]}" do # signal "32" and "33" are undefined if [[ "${binary_array_index}" == "32" || "${binary_array_index}" == "33" ]] then (( binary_array_index-- )) continue elif [[ "${binary_value}" == "0" ]] then (( binary_array_index-- )) continue elif [[ "${binary_value}" == "1" ]] then echo "Signal ${binary_array_index}: ${pid_signal_array[${binary_array_index}]}" fi (( binary_array_index-- )) done # output results, if there is any signal. also output results, if signal "32" and "33" are set to "1", which actually does not make any sense. if [[ "${pid_signal_bin_value_concatenated}" == *"1"* ]] then echo -e "Hexadecimal: ${pid_signal_hex_value_delimited_array[@]}\nBinary: ${pid_signal_bin_value_4bit_array[@]}" | column --table else echo "No signals found." fi done done } main "${@}" 
$ psig $$ PID: 10392 Name: zsh Signals caught: --------------- Signal 28: SIGWINCH Signal 17: SIGCHLD Signal 14: SIGALRM Signal 13: SIGPIPE Signal 2: SIGINT Signal 1: SIGHUP Hexadecimal: 0 0 0 0 0 0 0 0 0 8 0 1 3 0 0 3 Binary: 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000 0000 0001 0011 0000 0000 0011 Signals pending (process): -------------------------- No signals found. Signals pending (thread): ------------------------- No signals found. Signals blocked: ---------------- Signal 2: SIGINT Hexadecimal: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 Binary: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 Signals ignored: ---------------- Signal 22: SIGTTOU Signal 21: SIGTTIN Signal 20: SIGTSTP Signal 15: SIGTERM Hexadecimal: 0 0 0 0 0 0 0 0 0 0 3 8 4 0 0 0 Binary: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 1000 0100 0000 0000 0000 
0

I created a small script in bash to see all those signals for a process:

[mvutcovi@mvutcovi-lap2 ~]$ cat signals.sh #read -p "PID=" pid pid=$1 cat /proc/$pid/status|egrep '(Sig|Shd)(Pnd|Blk|Ign|Cgt)'|while read name mask;do bin=$(echo "ibase=16; obase=2; ${mask^^*}"|bc) echo -n "$name $mask $bin " i=1 while [[ $bin -ne 0 ]];do if [[ ${bin:(-1)} -eq 1 ]];then kill -l $i | tr '\n' ' ' fi bin=${bin::-1} set $((i++)) done echo done # vim:et:sw=4:ts=4:sts=4: [mvutcovi@mvutcovi-lap2 ~]$ sleep 1234 &./signals.sh $(pgrep -f "sleep .*1234");pkill sleep [1] 2613776 SigPnd: 0000000000000000 0 ShdPnd: 0000000000000000 0 SigBlk: 0000000000000000 0 SigIgn: 0000000000000000 0 SigCgt: 0000000000000000 0 [1]+ Terminated sleep 1234 [mvutcovi@mvutcovi-lap2 ~]$ nohup sleep 1234 &./signals.sh $(pgrep -f "sleep .*1234");pkill sleep [1] 2613812 nohup: ignoring input and appending output to 'nohup.out' SigPnd: 0000000000000000 0 ShdPnd: 0000000000000000 0 SigBlk: 0000000000000000 0 SigIgn: 0000000000000001 1 HUP SigCgt: 0000000000000000 0 [1]+ Terminated nohup sleep 1234 [mvutcovi@mvutcovi-lap2 ~]$ 
0

Awesome work on the bash scripts, thanks for sharing! In the bash psig.sh I had to change line 202 for it to work on Ubuntu 20.04. --table seems to have been deprecated so I changed it to -t.

before

~/bin$ psig.sh 2625 PID: 2625 Name: file.so Signals caught: --------------- Signal 15: SIGTERM Signal 11: SIGSEGV Signal 8: SIGFPE Signal 7: SIGBUS Signal 6: SIGABRT Signal 4: SIGKILL Signal 3: SIGQUIT Signal 2: SIGINT column: invalid option -- '-' usage: column [-txne] [-c columns] [-s sep] [file ...] 

after

:~/bin$ psig.sh 2625 PID: 2625 Name: file.so Signals caught: --------------- Signal 15: SIGTERM Signal 11: SIGSEGV Signal 8: SIGFPE Signal 7: SIGBUS Signal 6: SIGABRT Signal 4: SIGKILL Signal 3: SIGQUIT Signal 2: SIGINT Hexadecimal: 0 0 0 0 0 0 0 1 8 0 0 0 4 4 e e Binary: 0000 0000 0000 0000 0000 0000 0000 0001 1000 0000 0000 0000 0100 0100 1110 1110 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.