Re: systemd m'a tuer

Page principale

Répondre à ce message
Auteur: Edgar Bonet
Date:  
À: guilde
Sujet: Re: systemd m'a tuer
Bonsoir la Guilde !

Tout d'abord, je remercie tous ceux qui ont partagé leurs pistes, leurs
idées. Pour ceux que ça intéresse, voici l'épilogue de cette histoire.

Le plus simple a été de modifier le programme de calcul pour qu'il
intercepte SIGTERM, et qu'il sauvegarde alors son état avant de
quitter :

    https://github.com/feellgood/FeeLLGood/commit/fd20170c13


Pour envoyer ce signal j'ai créé, comme suggéré par plusieurs d'entre
vous, une sorte de service « virtuel » géré par systemd :

------------------------------------------------------------------------
# feellgood.service - Manage feeLLGood processes
#
# This service is intended to ensure that, when the system halts,
# running instances of feeLLGood are noticed with SIGTERM and given some
# time to save their state before being killed. The service does nothing
# when started and calls /usr/local/bin/stop-feellgood when stopped.

[Unit]
Description=Manage feeLLGood processes

[Service]
Type=oneshot
RemainAfterExit=yes
#ExecStart is not set
ExecStop=/usr/local/bin/stop-feellgood
TimeoutStopSec=10

[Install]
WantedBy=multi-user.target
------------------------------------------------------------------------

À noter que ce service ne fait rien quand il est lancé (ExecStart non
renseigné), mais systemd va quand même le considérer actif (grâce à la
ligne RemainAfterExit=yes). Comme indiqué dans systemd.service(5), ce
type de fonctionnement est possible uniquement pour les services de type
« oneshot ».

Quand le service est arrêté, il lance le script stop-feellgood qui se
charge d'arrêter le programme de calcul. Ce script est bloquant, mais
après 10 secondes maximum (TimeoutStopSec), systemd le tue et considère
que c'est fini. Ce délai est destiné à laisser un petit répit au
programme qui doit sauver son état.

Et voici le script qui fait le boulot :

------------------------------------------------------------------------
#!/bin/bash

# Stop all running instances of feeLLGood with SIGTERM, which gives them
# a chance to save their state before exiting. Then wait for them to
# exit. The wait is needed when using this script as the ExecStop field
# of a systemd service, otherwise, on poweroff, systemd would kill all
# process very shortly after launching the script.

pids=$(pidof feellgood)
if [ -z "$pids" ]; then
    echo "No processes to stop"
    exit
fi


echo "Sending SIGTERM to process $pids"
killall feellgood
while pidof -q feellgood; do
    sleep 0.1
done
echo "Process exited"
------------------------------------------------------------------------


À noter qu'il attend l'arrêt du programme de calcul, comme conseillé
dans systemd.service(5), à propos de ExecStop :

    Note that it is usually not sufficient to specify a command for
    this setting that only asks the service to terminate (for example,
    by sending some form of termination signal to it), but does not
    wait for it to do so. Since the remaining processes of the services
    are killed according to KillMode= and KillSignal= or
    RestartKillSignal= as described above immediately after the command
    exited, this may not result in a clean stop. The specified command
    should hence be a synchronous operation, not an asynchronous one.


Voilà, ça a pour l'instant l'air de marcher.

Bonne soirée !

Edgar.