J'ai rencontré ce problème alors que j'essayais de répondre à une question sur Stackoverflow .
À l’arrêt, Ubuntu 12.04 envoie SIGTERM
à tous les processus et attend au plus 10 secondes avant de les tuer avec SIGKILL
(sauf s’ils se sont arrêtés avant). Ma réponse à SO contient même un script Python qui vérifie ce comportement. Le script est démarré dans un terminal, envoyé en arrière-plan et désavoué par le terminal. Lors de la réception de SIGTERM
, le script continue de fonctionner et affiche continuellement dans un fichier la durée de son exécution après réception de SIGTERM
.
Ubuntu 16.04 cependant, le script est tué immédiatement à l’arrêt (aucun SIGTERM
n’est enregistré).
J'ai cherché sur Google pendant un moment, mais je n'ai rien trouvé d'utile. Est-ce que personne n'a jamais rencontré ce changement radical pour la version actuelle de LTS?
Voici le 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)
Le script utilise le fichier log.txt
dans le répertoire en cours pour toutes les sorties. Il a une boucle qui affiche "en cours" chaque seconde. Recevoir SIGTERM
interrompt la boucle et lance une autre boucle qui affiche les secondes écoulées depuis la réception de SIGTERM
.
Le script est exécuté à partir d'un terminal détaché à l'aide de disown
:
python signaltest.py &
disown
Juste pour être clair: Ceci n'est pas un doublon de buntu n'envoie pas de SIGTERM à l'arrêt . La question concerne les applications de bureau et les réponses ne correspondent pas non plus.
systemd (opposé à upstart dans les versions précédentes d'Ubuntu) envoie en outre SIGHUP à l'arrêt (et attend 90 secondes au lieu de 10 avant d'envoyer SIGKILL
). Je suggère d'ignorer SIGHUP
ou de traiter SIGTERM
et SIGHUP
de la même manière (idempotente).
Le script de test modifié pourrait être modifié comme suit:
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)