Tracing UNIX signal origins? - linux

If I have a process that receives signals from other processes, is there a way for me to somehow tell which process (if any) sent a signal?
strace lets me trace which signals a process has received, but doesn't allow me to trace who issued them.

Not from outside the process. The second argument to the signal handler is a siginfo_t structure which contains the PID of the sending process as one of its members. See sigaction(2) for more details.

For Linux users, there is a very easy way to identify the source of a signal. For example, the following is to find which task sends SIGKILL to others.
cd /sys/kernel/debug/tracing
echo 'sig==9' > events/signal/signal_generate/filter
echo 1 > events/signal/signal_generate/enable
: > trace
echo 1 > tracing_on
tail -f trace
One instance, when I used 'pkill -9 sleep'.
# cat trace
[...]
pkill-2982 [001] d... 750347.835838: signal_generate: sig=9 errno=0 code=0 comm=sleep pid=2981 grp=1 res=0
Without above 'sig==9' filter, 'trace' will show all signals sent among tasks.

Ptrace can be used to detect sender too. There is an ptrace(GETSIGINFO) call, which will give a debugger a chance to read (and, possibly, change) siginto_t struct.

Related

Is it possible to signal TSTP and then kill it if timeout occurs

Can I send a signal TSTP to PID , that after a period of time if the process is still "paused" - then kill it ?
thanks.
Should be a simple sequence of 3 operations, methinks: (1) send the TSTP signal to the pid, (2) sleep, and (3) read the third field of /proc/$pid/stat to see if it still equals T, and if so, send the KILL signal to it.
kill -TSTP $pid;
sleep 2;
if [[ "$(awk '{ print($3); };' </proc/$pid/stat;)" == 'T' ]]; then kill -KILL $pid; fi;
Useful documentation:
kill(1)
sleep(1)
proc(5) (scroll down to the section headed by /proc/[pid]/stat)
The above code and documentation inhabit the bash universe, but the same operations can be performed from C code almost as easily. It's a little more work, especially to open and read the /proc/$pid/stat (or /proc/$pid/status) pseudo-file, but the idea is the same. More documentation:
kill(2)
sleep(3)
fopen(3)/fread(3)/fscanf()/fclose(3); lots of good Stack Overflow threads here, e.g.
How to determine the state of a process (i.e. if it is a zombie)
Getting pid and other process information from /proc/<pid>/status
how to extract info in linux with a C code from /proc

What key combinations are associated with signals

I am writing some perl scripts and I want to utilize signals to perform certain routines at any time. I see all over the place the ability to print out what the signals are,
perl -e 'foreach (keys %SIG) { print "$_\n" }'
and I have already been using "INT" to go to a subroutine which is activated with ctrl+c.
I cant find anywhere what key combinations are associated with the other signals. Is there a list somewhere? The script I'm writing should work on mac and linux computers.
I know the ctrl+c signal is analogous between systems, what other "signals" can be utilized in perl and what keys activate them?
what other "signals" can be utilized in perl
These are the signal names recognized by Perl:
$ perl -V:sig_name
sig_name='ZERO HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS NUM32 NUM33 RTMIN NUM35 NUM36 NUM37 NUM38 NUM39 NUM40 NUM41 NUM42 NUM43 NUM44 NUM45 NUM46 NUM4 NUM48 NUM49 NUM50 NUM51 NUM52 NUM53 NUM54 NUM55 NUM56 NUM57 NUM58 NUM59 NUM60 NUM61 NUM62 NUM63 RTMAX IOT CLD POLL UNUSED ';
The above list can also be obtained from Config.pm's $Config{sig_name}.
There's also the two pseudo signals, __WARN__ and __DIE__.
and what keys activate them?
The following signals are often sent in response to terminal input:
SIGINT
SIGQUIT is a more "serious" version of SIGINT that provides a core dump.
SIGTSTP sends a process to the background.
SIGSTOP is an uncatchable signal that freezes the process.
SIGCONT resumes a process frozen by SIGSTOP.
You can see to what key these are bound using the following:
$ stty -a | perl -ne'
$b{$1}=$2 while /\b(intr|quit|susp|stop|start)\s*=\s*([^\s;]+)/g;
END {
print "SIGINT: $b{intr}\n";
print "SIGQUIT: $b{quit}\n";
print "SIGTSTP: $b{susp}\n";
print "SIGSTOP: $b{stop}\n";
print "SIGCONT: $b{start}\n";
}
'
SIGINT: ^C
SIGQUIT: ^\
SIGTSTP: ^Z
SIGSTOP: ^S
SIGCONT: ^Q
Most signals aren't sent as a result of terminal input. The following a commonly used signals and what normally causes them to be sent:
SIGSEGV is sent when the program does an illegal operation (often the result of using a bad pointer).
SIGHUP is sent when the session's terminal disconnects.
SIGTERM is sent to request that a process exits.
SIGKILL can't be caught. It's sent to forcibly terminate a process.
SIGCHLD is sent when a child exits.
SIGALRM is sent by alarm.
SIGPIPE is sent when writing a pipe with a closed read end.

Signal handling: printing something and then taking the default behaviour

My requirement is that whenever a program terminates in any way other than its normal completion [i.e. exit() system call at the end], I need to handle it (say, hook a print "Hello" statement) before it actually terminates.
For example, when I hit Ctrl+C while running a program, it should print Hello and continue the way a SIGINT must have been handled.
If I use my custom signal handler function (having a print statement logic) in my source code, it would alter the default behavior i.e. how SIGINT would have ideally terminated.
1) Can anyone help me achieve both of this? What other signals I need to handle explicitly (maybe SIGTERM ?) which can cause termination of a running process?
2) How can I generate/test them ?(say, SIGINT can be generated by hitting Ctrl + C in linux)
there are several signals supported in unix/linux.
Except SIGKILL, SIGSTOP, all others can be interpreted and handled.
process of registering the handler to a particular signumber should be same.
We can use kill command to send signals to other process.
For example: it sends TERM signal to processid 1234
kill -s TERM 1234
The sigaction(2) man page has some useful info. For one thing, every signal but SIGKILL and SIGSTOP can be caught.
In your signal handler, you have two options:
puts(3) and then manually do something (exit() or raise(SIGSTOP) or something).
puts(3) and then try to get the default signal behaviour by setting the handler back to SIG_DFL, and sending the signal to yourself with raise(3). I'm not sure whether you can just sigaction() to restore your signal handler right after raise() from inside that signal handler, and whether that would be portable even if it happens to work on Linux.
List all signals with kill -l
Send a signal with kill -INT 1234, or in the shell you started a background process from: kill -INT %1. Or to avoid copy/pasting a PID every time: pkill -INT process_name (pkill and pgrep are related.)

Timing traps in a shell script

I have a shell script background process that runs "nohupped". This process shall receive signals in a trap, but when playing around with some code, I noticed that some signals are ignored if the interval between them is too small. The execution of the trap function takes too much time and therefore the subsequent signal goes
unserved. Unfortunately, the trap command doesn't have some kind of signal queue, that's why I am asking: What is the best way to solve this problem?
A simple example:
function receive_signal()
{
local TIMESTAMP=`date '+%Y%m%d%H%M%S'`
echo "some text" > $TIMESTAMP
}
trap receive_signal USR1
while :
do
sleep 5
done
The easiest change, without redesigning your approach, is to use realtime signals, which queue.
This is not portable. Realtime signals themselves are an optional extension, and shell and utility support for them are not required by the extension in any case. However, it so happens that the relevant GNU utilities on Linux — bash(1) and kill(1) — do support realtime signals in a commonsense way. So, you can say:
trap sahandler RTMIN+1
and, elsewhere:
$ kill RTMIN+1 $pid_of_my_process
Did you consider multiple one line trap statements? One for each signal you want to block or process?
trap dosomething 15
trap segfault SEGV
Also you want to have the least possible code in a signal handler for the reason you just encountered.
Edit - for bash you can code your own error handling / signal handling in C, or anything else using modern signal semantics if you want with dynamically loadable modules:
http://cfajohnson.com/shell/articles/dynamically-loadable/

How to poll multiple pids with monit

I have a script which spawns mutiple pids, outputting something like:
processname.eth4.pid
processname.eth5.pid
processname.eth8.pid
Currently i am monitoring indiviual pids like so:
check process perl
with pidfile /var/run/processname.eth4.pid
start = "/usr/bin/perl /usr/local/etc/script.pl"
stop = "/bin/cat /var/run/processname.eth4.pid | /usr/bin/xargs kill -9"
Is there a way monit can poll multiple pids without using multiple statements for individual pids?
You might use trap check_children SIGCHLD to be notified on SIGCHLD and define the function check_children to detect which of the processes is still living and wich not.
Type help trap in bash for more info.

Resources