4

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
  • Why such a roundabout way and not kill(2)? – muru Nov 13 '14 at 14:10
  • I am new to linux, had no idea about that command. I assume just sudo kill(1, <1 to 64>)) ? But anyway, I am more interested in how to log how the init reacts to it. – LookingForKnowledge Nov 13 '14 at 14:14
  • Yes, something like: for(i=0;i<64;i++) { kill (1, i); }. The question is what do you mean, how init reacts? If it crashes, you get a kernel panic and you won't be able to do anything. You cannot deliver killing signals (see documentation of kill(2), or this SO question). That leaves signals which cause init to reload or voluntarily shutdown, both of which should leave traces in /var/log/syslog, I think. – muru Nov 13 '14 at 14:30
4

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 32

Of these:

  • SIGABRT and SIGSEGV caused core dumps and kernel panics. Nothing to be detected here.
  • SIGTERM caused 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, respawning
    
  • SIGINT caused it to start a reboot, and SIGPWR started a shutdown. Both looked like normal ones (say, like if you did a reboot, for example).
  • None of the others caused any visible effects. (Though, considering init's duties, we can guess what SIGCHLD does.)

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 | column
  • HANDLED_SIGS=$(awk '/SigCgt/{print "0x"$2}' /proc/1/status): /proc/$PID/status contains a wealth of information about the process, including the set of handled signals. This set is given by SigCgt, a bitmask given as a hexadecimal number. We use awk to extract that number and add 0x as a prefix.
  • (( (1 << i) & $HANDLED_SIGS )): check if signal no. (i+1) is masked. Since we're concerned about the ith bit, we use 2(i-1) (which is 1 << i). With (( )), a non-zero value indicates success.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.