I have to write a C program to check how init reacts to different kill signals, however I am not sure how to log it - for example signal number 14 crashes the ubuntu, then some higher one turns it off. Is there any way to log it properly so that I know how does system react to each signal? Here is the C code I use, any feedback on that would be also appreciated:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{ int sigs[64] = { 0 }; for(int i = 0; i < 64; i++) sigs[i] = i+1; char sigs_char[64][2]; for(int i = 0; i < 64; i++) sprintf(sigs_char[i], "%d", sigs[i]); char one[2] = " 1"; char commands[64][128]; for(int i = 0; i < 64; i++){ strcpy(commands[i], "sudo kill -s "); strncat(commands[i], sigs_char[i], 2); strcat(commands[i], one); } for(int i = 0; i < 64; i++){ printf("Sending signal number %d\n", i); system(commands[i]); } return 0;
} 3 1 Answer
I'm afraid there's no general way to "log" init's reaction. First, there's the fact that kill won't deliver any signals to init that init isn't handling (from man 2 kill):
NOTES The only signals that can be sent to process ID 1, the init process, are those for which init has explicitly installed signal handlers. This is done to assure the system is not brought down accidentally.So, for many signals, there won't be a reaction at all. Now that leaves the signals that are handled. Using this Unix & Linux question, we can determine those1:
$ HANDLED_SIGS=$(awk '/SigCgt/{print "0x"$2}' /proc/1/status)
$ for i in {0..31}; do (( (1 << i) & $HANDLED_SIGS )) && echo $((++i)) $(/bin/kill --list=$i); done | column
1 HUP 6 ABRT 11 SEGV 15 TERM 30 PWR
2 INT 10 USR1 14 ALRM 17 CHLD 32Of these:
SIGABRTandSIGSEGVcaused core dumps and kernel panics. Nothing to be detected here.SIGTERMcaused it to reload, with log messages in/var/log/syslog:Nov 14 00:25:13 vm kernel: [32383.384907] init: upstart-udev-bridge main process (395) terminated with status 1 Nov 14 00:25:13 vm kernel: [32383.384916] init: upstart-udev-bridge main process ended, respawning Nov 14 00:25:13 vm kernel: [32383.384990] init: upstart-socket-bridge main process (649) terminated with status 1 Nov 14 00:25:13 vm kernel: [32383.384995] init: upstart-socket-bridge main process ended, respawning Nov 14 00:25:13 vm kernel: [32383.385059] init: upstart-file-bridge main process (953) terminated with status 1 Nov 14 00:25:13 vm kernel: [32383.385074] init: upstart-file-bridge main process ended, respawningSIGINTcaused it to start a reboot, andSIGPWRstarted a shutdown. Both looked like normal ones (say, like if you did areboot, for example).- None of the others caused any visible effects. (Though, considering
init's duties, we can guess whatSIGCHLDdoes.)
And all this is for Upstart. Who knows how SysV or systemd will react?
So, all in all, you're not going to have much luck with empirical methods here. Use the Source, Luke.
1That convoluted bit of code is for getting the signals that init is willing to catch:
HANDLED_SIGS=$(awk '/SigCgt/{print "0x"$2}' /proc/1/status)
for i in {0..31}
do (( (1 << i) & $HANDLED_SIGS )) && echo $((++i)) $(/bin/kill --list=$i);
done | columnHANDLED_SIGS=$(awk '/SigCgt/{print "0x"$2}' /proc/1/status):/proc/$PID/statuscontains a wealth of information about the process, including the set of handled signals. This set is given bySigCgt, a bitmask given as a hexadecimal number. We useawkto extract that number and add0xas a prefix.(( (1 << i) & $HANDLED_SIGS )): check if signal no.(i+1)is masked. Since we're concerned about theith bit, we use 2(i-1) (which is1 << i). With(( )), a non-zero value indicates success.