Job control is enabled by default, but it's usually disabled in scripts.
When job control is disabled, bash
makes processes, that it starts asynchronously (... &
), ignore SIGINT
:
When job control is not in effect, asynchronous commands ignore SIGINT and SIGQUIT in addition to these inherited handlers.
a.py
:
import signal
print('getsignal()', signal.getsignal(signal.SIGINT))
print('SIG_IGN?', signal.getsignal(signal.SIGINT) == signal.SIG_IGN)
$ echo $-
smi (job control is enabled)
$ python a.py &
getsignal() <built-in function default_int_handler>
SIG_IGN? False
[1]+ Done python a.py
$ bash -c 'echo $-; python a.py &'
hBc (job control is not enabled)
getsignal() 1
SIG_IGN? True
Let's take a more long-running process and try to kill it:
b.py
:
import signal
import time
import sys
print('getsignal()', signal.getsignal(signal.SIGINT))
print('SIG_IGN?', signal.getsignal(signal.SIGINT) == signal.SIG_IGN)
if len(sys.argv) > 1 and sys.argv[1] == 'reset-sigint':
signal.signal(signal.SIGINT, signal.SIG_DFL)
print('getsignal()', signal.getsignal(signal.SIGINT))
print('SIG_IGN?', signal.getsignal(signal.SIGINT) == signal.SIG_IGN)
while True:
print('.', end='', flush=True)
time.sleep(2)
$ python e.py &
[1] 245
getsignal() <built-in function default_int_handler>
SIG_IGN? False
..........
$ echo "ibase=16; obase=2; $(ps -p `pgrep python` -o ignored=)" | bc
1000000000001000000000000
$ pkill -2 python
Traceback (most recent call last):
File "//e.py", line 16, in <module>
time.sleep(2)
KeyboardInterrupt
[1]+ Interrupt python e.py
$ bash -c 'python e.py &'
getsignal() 1
SIG_IGN? True
......
$ echo "ibase=16; obase=2; $(ps -p `pgrep python` -o ignored=)" | bc
1000000000001000000000110
$ pkill -2 python
...
$ pkill python
$ bash -c 'python e.py reset-sigint &'
getsignal() 1
SIG_IGN? True
getsignal() 0
SIG_IGN? False
...
$ echo "ibase=16; obase=2; $(ps -p `pgrep python` -o ignored=)" | bc
1000000000001000000000100
$ pkill -2 python