Why would Ctrl-C behave differently than kill -2

9,533

Solution 1

One possibility is that the program catches the Ctrl+C sequence. Check the output of stty -a; the intr setting indicates which key combination (if any) sends a SIGINT signal, and the isig indicates whether the signal keys are enabled (-isig means they are disabled).

If the program consists of several processes, pressing Ctrl+C sends SIGINT to all the processes in the process group. You can obtain the same effect by sending the signal to the process group instead of sending it to one of the processes. To send a signal to a process group, first determine its leader: that's the first process that starts all the others; if you run the process group in the background, that's the PID shown by jobs -l. The PID of the process group leader is the PGID (process group id); send the signal to its negative. E.g. if the PGID is 1234, run kill -INT -1234.

If the program consists of a wrapper script and a main application, there are two cases to consider. If there is no cleanup to do, so that the wrapper script terminates as soon as the main aplication terminates, make the wrapper script call exec:

#!/bin/sh
export SOMEVAR=somevalue
…
exec /path/to/application "$@"

This way the application replaces the script, inheriting its PID. Some shells optimize a script that ends by executing another program, but not all. This approach doesn't work when the script needs to perform some cleanup such as removing temporary files.

Consider making the script detect a signal and transmitting the signal to the application. Here's a sketch of how this goes:

/path/to/application "$@" &
app_pid=$!
trap -INT 'kill -INT $app_pid'
wait $!
rm /temp/file

Solution 2

Based on the questions @Gilles asked in the comments to my original question I realized that the kill -2 command I was sending was targeting the pid of the wrapper script which launched the application instead of the process which handles the signal itself.

Using the pids from my question, kill -s 13405 was not properly signaling the application, but calling kill -s 13509 works as expected.

Now my question is how can I update my wrapper script to propagate a SIGINT to its child processes, but I'll create a separate question for that.

Share:
9,533

Related videos on Youtube

Mike Deck
Author by

Mike Deck

Updated on September 18, 2022

Comments

  • Mike Deck
    Mike Deck over 1 year

    I have a program which is supposed to handle SIGINT and gracefully shut down. When I run this program from a terminal without backgrounding it I can shut it down just fine using Ctrl-C. Inspecting the logs shows that everything worked as expected.

    When I open a separate terminal and call kill -2 [pid] or kill -s INT [pid] it does nothing. I see nothing in the logs and the program continues to run as usual until I hit Ctrl-C in the terminal I launched it from.

    Are there any differences between how Ctrl-C sends the signal and how kill does?

    Additional Details:

    The program in question is a Java application launched by a bash shell script which sets up some environment variables (namely CLASSPATH) and then calls java [main class]. Hitting Ctrl-Z and then running ps results in the following:

    $ ps -f
    UID        PID  PPID  C STIME TTY          TIME CMD
    mdeck    10251 10250  0 11:48 pts/2    00:00:00 -bash
    mdeck    13405 10251  0 18:12 pts/2    00:00:00 /bin/bash /usr/local/bin/myapp.sh
    mdeck    13509 13405 25 18:12 pts/2    00:00:03 java com.company.MyApp
    mdeck    13526 10251  0 18:13 pts/2    00:00:00 ps -f
    

    The output of stty as requested by Gilles is below:

    $ stty -a </dev/pts/2
    speed 38400 baud; rows 40; columns 203; line = 0;
    intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
    -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
    -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
    opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
    isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
    
    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' almost 12 years
      Does the program run in a single process? Does the program capture Ctrl+C instead of reacting to a signal? What is the output of stty -a </dev/pts/42 where /dev/pts/42 is the output of tty in the terminal where you start the process?
    • Mike Deck
      Mike Deck almost 12 years
      @Gilles, I've updated the question to include some of the information you're requesting.