3

I ran across this problem while I tried to answer a question on Stackoverflow.

On shutdown, Ubuntu 12.04 sends SIGTERM to all processes and waits at most 10 seconds before killing them with SIGKILL (unless they terminated before). My answer on SO even contains a Python script that verifies that behaviour. The script is started in a terminal, sent to the background and than disowned by the terminal. When receiving SIGTERM, the script just keeps going and continuously prints to a file how long it has been running after receiving SIGTERM.

Ubuntu 16.04 however, the script is killed immediately on shutdown (no SIGTERM is logged).

I googled for a while, but I could not find anything useful. Has nobody ever come across that breaking change for the current LTS release?

Here is the script signaltest.py

import signal
import time

stopped = False

out = open('log.txt', 'w')

def stop(sig, frame):
    global stopped
    stopped = True
    out.write('caught SIGTERM\n')
    out.flush()

signal.signal(signal.SIGTERM, stop)

while not stopped:
    out.write('running\n')
    out.flush()
    time.sleep(1)

stop_time = time.time()
while True:
    out.write('%.4fs after stop\n' % (time.time() - stop_time))
    out.flush()
    time.sleep(0.1)

The script uses the file log.txt in the current directory for all output. It has a loop that prints 'running' every second. Receiving SIGTERM breaks the loop ans starts another loop which prints the seconds elapsed since receiving SIGTERM.

The script is run from a terminal a detached using disown:

python signaltest.py &
disown

Just to be clear: This is not a duplicate of Ubuntu is not sending SIGTERM on shutdown. The question is about desktop applications and the answers do not fit either.

1 Answers1

4

systemd (opposed to upstart in earlier Ubuntu verions) additionally sends SIGHUP on shutdown (and waits 90s instead of 10s before sending SIGKILL). I suggest to ignore SIGHUP or to handle SIGTERM and SIGHUP the same (idempotent) way.

The modified test script could be changed like this:

import signal
import time

stopped = False

out = open('log.txt', 'w')

def stop(sig, frame):
    global stopped
    stopped = True
    out.write('caught SIGTERM\n')
    out.flush()

def ignore(sig, frsma):
    out.write('ignoring signal %d\n' % sig)
    out.flush()

signal.signal(signal.SIGTERM, stop)
signal.signal(signal.SIGHUP, ignore)

while not stopped:
    out.write('running\n')
    out.flush()
    time.sleep(1)

stop_time = time.time()
while True:
    out.write('%.4fs after stop\n' % (time.time() - stop_time))
    out.flush()
    time.sleep(0.1)