I start a process group from bash. Then I send SIGINT to the entire process group. Sometimes the SIGINT kills the processes, sometimes does not. Why does SIGINT sometimes gets ignored ?
I see different behavior depending on whether the process group is started in the background or not, on nestedness of bash shells and on Mac/Linux operating system. I would really appreciate if someone can shed some light on this.
In the following examples I use this python executable called sleep_in_pgrp.py
#!/usr/bin/env python2.7
import os;
import subprocess
os.setpgrp();
subprocess.check_call(["sleep","10000"]);
It creates a process group and starts sleep. The observed phenomena should not
be related to python. I use python only because bash does not have a setpgrp
command or builtin. Update: Apparently one could also run an interactive
shell to create a new process group
1) Start the process group in the background and wait on the leader. SIGINT gets ignored.
Execute the following command:
$ bash -c ' { sleep_in_pgrp.py; } & wait $! '
Bash starts python in the background and waits on it. In another terminal:
$ ps -Heo pid,ppid,tpgid,pgid,sid,user,args
PID PPID TPGID PGID SID COMMAND
2507 1574 2963 2507 2507 -bash
2963 2507 2963 2963 2507 bash -c { sleep_in_pgrp.py; } & wait $!
2964 2963 2963 2963 2507 bash -c { sleep_in_pgrp.py; } & wait $!
2965 2964 2963 2965 2507 python2.7 ./sleep_in_pgrp.py
2966 2965 2963 2965 2507 sleep 10000
SIGINT’ing the proccess group of python does not kill any processes. What can be the reason ?
$ sudo kill -s SIGINT -- -2965
2) Start the process group in the foreground. SIGINT works.
If I remove the & wait $!
, SIGINT kills the process group as expected. I do not know why but I am not surprised SIGINT killed the processes in this case.
$ bash -c ' { sleep_in_pgrp.py; } '
In another terminal:
$ ps -Heo pid,ppid,tpgid,pgid,sid,user,args
PID PPID TPGID PGID SID COMMAND
2507 1574 3352 2507 2507 -bash
3352 2507 3352 3352 2507 bash -c { sleep_in_pgrp.py; }
3353 3352 3352 3353 2507 python2.7 ./sleep_in_pgrp.py
3354 3353 3352 3353 2507 sleep 10000
SIGINT kills the process group.
$ sudo kill -s SIGINT -- -3353
3) Removing the subshell while running python in the background. SIGINT works.
I was very surprised that the shell nestedness affects the behavior here. I cannot think of any explanation why.
I remove the bash -c
at the start:
$ { sleep_in_pgrp.py; } & wait $!
In another terminal:
$ ps -Heo pid,ppid,tpgid,pgid,sid,user,args
PID PPID TPGID PGID SID COMMAND
2507 1574 2507 2507 2507 -bash
3488 2507 2507 3488 2507 -bash
3489 3488 2507 3489 2507 python2.7 ./sleep_in_pgrp.py
3490 3489 2507 3489 2507 sleep 10000
SIGINT kills the process group.
$ sudo kill -s SIGINT -- -2507
4) Running the first command in Mac: SIGINT works.
The first 2 commands ran in a CentOs7 VM.
$ uname -a
Linux ip-10-229-193-124 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 13 10:46:25 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux
I now execute the first command with backgrounded python in a subshell in mac.
$ uname -a
Darwin mbp-005063 15.6.0 Darwin Kernel Version 15.6.0: Sun Jun 4 21:43:07 PDT 2017; root:xnu-3248.70.3~1/RELEASE_X86_64 x86_64
In Mac:
$ bash -c ' { sleep_in_pgrp.py; } & wait $! '
In another terminal:
$ PID PPID TPGID PGID SESS COMMAND
18741 40096 18741 18741 0 bash -c { sleep_in_pgrp.py; } & wait $!
18742 18741 18741 18741 0 bash -c { sleep_in_pgrp.py; } & wait $!
18743 18742 18741 18743 0 /usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python ./sleep_in_pgrp.py
18744 18743 18741 18743 0 sleep 10000
40094 2423 18741 40094 0 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server /usr/bin/login -fpl hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2 --launch_shell
40095 40094 18741 40095 0 /usr/bin/login -fpl hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2 --launch_shell
40096 40095 18741 40096 0 -bash
-+= 00001 root /sbin/launchd
\-+= 02423 hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2
\-+= 40094 hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2 --server /usr/bin/login -fpl hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2 --launch_shell
\-+= 40095 root /usr/bin/login -fpl hbaba /Applications/iTerm.app/Contents/MacOS/iTerm2 --launch_shell
\-+= 40096 hbaba -bash
\-+= 18741 hbaba bash -c { sleep_in_pgrp.py; } & wait $!
\-+- 18742 hbaba bash -c { sleep_in_pgrp.py; } & wait $!
\-+= 18743 hbaba /usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python ./sleep_in_pgrp.py
\--- 18744 hbaba sleep 10000
And in this case, SIGINT also kills the process group
$ sudo kill -s INT -18743
Bash version in CentOs7 is
$ echo $BASH_VERSION
4.2.46(2)-release
In Mac the bash version is
$ echo $BASH_VERSION
4.4.12(1)-release
This answer explains how Ctrl+C sends SIGINT to the process group. That is what I am trying to do here sending SIGINT to a process group. This answer mentions that non interactive jobs require a SIGINT handler. I am not sure it explains the varying behavior I see. I am also wondering whether waiting on a background process affects the SIGINT handling by that process.