Page 1 sur 2

[systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 10:45
par cycyx
Bonjour,

Merci de me signaler/déplacer si je ne suis pas dans la bonne section.

J'essaye de créer un script (shell, ruby, le problème est le même) qui serait "daemon-isé" par systemd, avec un watchdog (relance si il ne répond pas depuis X secondes.

Précision : je fais cela avec l'instance utilisateur de systemd, pas l'instance system (option --user) !

Voici le script :

Code : Tout sélectionner

#!/bin/sh

timeout=5
pid=$$

#trap "systemd-notify --pid=$pid --status='Aborting'" 0 1 3 6 9 15
trap "systemd-notify --status='Aborting'" 0 1 3 6 9 15

#systemd-notify --pid=$pid --ready
systemd-notify --ready

if [ $? -ne 0 ]; then
  logger "Not running under systemd. Aborting."
  exit 1
else
  logger "Sytemd environment: NOTIFY_SOCKET=$NOTIFY_SOCKET WATCHDOG_USEC=$WATCHDOG_USEC WATCHDOG_PID=$WATCHDOG_PID"
fi

while true; do
    #systemd-notify --pid=$pid WATCHDOG=1
    systemd-notify WATCHDOG=1
    sleep $timeout
done

# EoF
Et le "unit file" associé :

Code : Tout sélectionner

[Unit]
Description=Test Unit

[Service]
Type=notify
ExecStart=/home/cyriac/tt.sh
NotifyAccess=all
WatchdogSec=10
Restart=always

[Install]
WantedBy=default.target
Dans tous les cas (avec l'argument "--pid" ou pas), le watchdog redémarre le script au bout de 10 secondes, car dans les logs j'ai soit :
Failed to notify init system: Invalid argument
si j'utilise "--pid' ou :
Cannot find unit for notify message of PID 25869.
si je ne l'utilise pas.

Bref, quelqu'un a-t'il réussit à faire ce genre de chose ?

Merci..

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 11:50
par benjarobin
Bonjour,
J'ai essayé en tant que service system, et je pense qu'il y a un sacré bug dans cette chose... Cela fonctionne 1 fois sur 20 l'envoi d'un message via notify... Mon test :

Code : Tout sélectionner

sleep 0.1
systemd-notify --ready --status="Init done..." || echo "Fail notify"
cpt=1
while : ; do
  sleep 0.1
  cpt=$((cpt+1))
  #echo "... $cpt"
  systemd-notify --ready --status="Waiting $cpt ..." || echo "Fail status"
done

Code : Tout sélectionner

[Unit]
Description=Test Unit

[Service]
Type=notify
ExecStart=/home/benjarobin/test.sh
NotifyAccess=all

[Install]
WantedBy=multi-user.target
J'ai du mettre le --ready dans la boucle car le premier est prit en compte une fois sur 20, comme tous les autres messages. Si on fait un status on vois que le message de statut n'est des fois pas rafraichis alors que la boucle tourne toujours...

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 12:00
par cycyx
Je suis bien d'accord avec toi, d'où ma question ! :)

Parce que le *vrai* problème est le suivant : de temps en temps, mon script s'arrête tout seul (et sans log...), mais du coup systemd peut le relancer.
Par contre, de temps en temps, le script (un des processus fils en fait fige, donc il tourne toujours (on le voit avec un ps par exemple), mais il ne fait plus rien .
Et dans ce cas, je voudrais pouvoir le relancer aussi et le watchdog me semblait une bonne idée.

Une idée pour un workaround ?

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 12:07
par benjarobin
Si on continue les tests :

Code : Tout sélectionner

#!/bin/bash

BASH_PID=$$
sleep 0.1
systemd-notify --pid=$BASH_PID --ready --status="Init done..." || echo "Fail notify"
cpt=1
while : ; do
  sleep 0.5
  cpt=$((cpt+1))
  echo "systemd-notify --pid=$BASH_PID --ready --status=\"Waiting $cpt ...\""
  systemd-notify --pid=$BASH_PID --ready --status="Waiting $cpt ..."
done
Cela donne ceci est statut :

Code : Tout sélectionner

systemctl status -l test.service
● test.service - Test Unit
   Loaded: loaded (/etc/systemd/system/test.service; disabled; vendor preset: disabled)
   Active: activating (start) since sam. 2015-09-19 12:02:09 CEST; 7s ago
 Main PID: 24875 (test.sh)
   CGroup: /system.slice/test.service
           ├─24875 /bin/bash /home/benjarobin/test.sh
           └─24948 sleep 0.5

sept. 19 12:02:15 benjarobin-fixe test.sh[24875]: systemd-notify --pid=24875 --ready --status="Waiting 11 ..."
sept. 19 12:02:15 benjarobin-fixe test.sh[24875]: Failed to notify init system: Invalid argument
sept. 19 12:02:15 benjarobin-fixe test.sh[24875]: systemd-notify --pid=24875 --ready --status="Waiting 12 ..."
sept. 19 12:02:15 benjarobin-fixe test.sh[24875]: Failed to notify init system: Invalid argument
Par contre si on modifie la chose comme ceci :

Code : Tout sélectionner

#!/bin/bash

BASH_PID=$$
sleep 0.1
systemd-notify --pid=$BASH_PID --ready --status="Init done..." || echo "Fail notify"
cpt=1
while : ; do
  sleep 0.5
  cpt=$((cpt+1))
  echo "systemd-notify MAINPID=$BASH_PID --ready --status=\"Waiting $cpt ...\""
  systemd-notify MAINPID=$BASH_PID --ready --status="Waiting $cpt ..."
done
On obtient ceci :

Code : Tout sélectionner

systemctl status -l test.service
● test.service - Test Unit
   Loaded: loaded (/etc/systemd/system/test.service; disabled; vendor preset: disabled)
   Active: active (running) since sam. 2015-09-19 12:04:00 CEST; 2s ago
 Main PID: 25090 (test.sh)
   Status: "Waiting 2 ..."
   CGroup: /system.slice/test.service
           ├─25090 /bin/bash /home/benjarobin/test.sh
           └─25122 sleep 0.5

sept. 19 12:04:00 benjarobin-fixe systemd[1]: Starting Test Unit...
sept. 19 12:04:00 benjarobin-fixe test.sh[25090]: Failed to notify init system: Invalid argument
sept. 19 12:04:00 benjarobin-fixe test.sh[25090]: Fail notify
sept. 19 12:04:00 benjarobin-fixe test.sh[25090]: systemd-notify MAINPID=25090 --ready --status="Waiting 2 ..."
sept. 19 12:04:00 benjarobin-fixe systemd[1]: Started Test Unit.
sept. 19 12:04:01 benjarobin-fixe test.sh[25090]: systemd-notify MAINPID=25090 --ready --status="Waiting 3 ..."
sept. 19 12:04:01 benjarobin-fixe test.sh[25090]: systemd-notify MAINPID=25090 --ready --status="Waiting 4 ..."
========> Donc voici un truc de fonctionnel (enfin je crois)

Code : Tout sélectionner

#!/bin/bash

BASH_PID=$$
sleep 0.1
systemd-notify MAINPID=$BASH_PID --ready --status="Init done..."
cpt=1
while : ; do
  sleep 1
  cpt=$((cpt+1))
  echo "systemd-notify MAINPID=$BASH_PID --ready --status=\"Waiting $cpt ...\""
  systemd-notify MAINPID=$BASH_PID WATCHDOG=1 --status="Waiting $cpt ..."
done
Edit: None cela ne fonctionne pas mieux !!!

Edit2 / Conclusion : Il y a 2 bugs : L'option --pid ne fonctionne pas, par contre MAINPID= oui. Le problème c'est que les messages de notifications ne sont pas toujours reçus par systemd, avec ou sans MAINPID=

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 12:56
par cycyx
Oui, mes tests arrivent à la même conclusion : systemd-notify ne fonctionne pas *du tout*.

Du coup, cela ne sert même à rien de le diffuser avec systemd...

Mais à priori, ce bug a été reporté maintes fois et est toujours marqué comme résolu pour la release suivante.

Déçu je suis. Énervé aussi.

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 14:55
par benjarobin
Je suis en train de debug la chose, il y a déjà une erreur de doc, et une belle erreur dans le code, mais cela ne devrait corriger que l'option pid... Je confirme et je fais un rapport de bug avec le patch

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 14:55
par Xorg
Et voilà une des faiblesses de Systemd. À force de vouloir trop en faire, certaines choses ne fonctionnent juste pas !
Comme quoi, Systemd se moque éperdument de ses utilisateurs, vu qu'on est bien loin de la philosophie Unix «Écrivez des programmes qui effectuent une seule chose et qui le font bien». On me dira que Systemd est conçu pour Linux (!= Unix)...

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 15:16
par benjarobin
Vous parlez de ce bug là : https://bugs.freedesktop.org/show_bug.cgi?id=75680 ?
Sinon hum: Sorry, entering a bug into the product systemd has been disabled. "

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 15:22
par cycyx
Oui, c'était celui-là.

Sympa pour le reporting de bug ! :p

Il faut peut-être tenter la mailing-list directement ?

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 15:52
par benjarobin
On n'a pas le droit de poster sur la mailing-list de systemd-bug, je vais essayer systemd-devel... Pour information le patch

Code : Tout sélectionner

From 71df9aaefdecbb91b5ca189b7b426aeb4bf3ac4a Mon Sep 17 00:00:00 2001
From: Benjamin Robin <dev@benjarobin.fr>
Date: Sat, 19 Sep 2015 15:08:27 +0200
Subject: [PATCH] Fix sd_pid_notify_with_fds with valid pid. The msg_controllen
 was invalid, CMSG_SPACE(0) is not equal to 0

Signed-off-by: Benjamin Robin <dev@benjarobin.fr>
---
 src/libsystemd/sd-daemon/sd-daemon.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index d230a48..f7608c7 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -395,8 +395,12 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
         have_pid = pid != 0 && pid != getpid();
 
         if (n_fds > 0 || have_pid) {
-                msghdr.msg_controllen = CMSG_SPACE(sizeof(int) * n_fds) +
-                                        CMSG_SPACE(sizeof(struct ucred) * have_pid);
+                if (n_fds > 0) {
+                        msghdr.msg_controllen += CMSG_SPACE(sizeof(int) * n_fds);
+                }
+                if (have_pid) {
+                        msghdr.msg_controllen += CMSG_SPACE(sizeof(struct ucred));
+                }
                 msghdr.msg_control = alloca(msghdr.msg_controllen);
 
                 cmsg = CMSG_FIRSTHDR(&msghdr);
-- 
2.5.1


Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 16:01
par cycyx
Ils doivent en avoir marre de recevoir du flood de gens qui leur disent que systemd c'est le mal...

Sinon, ton patch corrige l'option --pid de systemd-notify, tu as bien testé ? (pas moi : j'ai la flemme de recompiler le package là, maintenant tout de suite... :p)

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 16:24
par benjarobin
Non, non je ne test jamais rien... Cela compile donc cela fonctionne tel est mon dicton. (humour second degré...)
http://lists.freedesktop.org/archives/s ... 34310.html

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 16:39
par cycyx
Merci pour le message et pour ton patch.

En fait, je crois qu'il y a un autre bug.

Après avoir lu la source de notify.c, j'avais vu que si on ne passais pas l'option --pid (ni MAINPID), systemd-notify devait appeler la fonction getppid et utiliser le PID du processus père. Or à priori, cela ne fonctionne pas non plus. A moins que ton patch n'est corrigé cela aussi.

Bref, je ne suis pas développeur (j'aurais été incapable de faire ton patch...), mais il sembe y avoir quand même des lacunes sur cet utilitaire.

Et rassure-toi, c'était aussi du second degré ma boutade sur tes tests. ;)

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 16:53
par benjarobin
Non, non, systemd-notify n'a pas besoin d'appeler la fonction getppid, il passe simplement 0 dans ce cas là, c'est géré par les couches plus basses.
Edit: Hum, du me met un gros doute... je vais creuser un peu plus

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 16:58
par cycyx
notify.c, lignes 96 à 106 :

Code : Tout sélectionner

                case ARG_PID:

                        if (optarg) {
                                if (parse_pid(optarg, &arg_pid) < 0) {
                                        log_error("Failed to parse PID %s.", optarg);
                                        return -EINVAL;
                                }
                        } else
                                arg_pid = getppid();

                        break;

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 17:04
par benjarobin
Donc tu n'as pas totalement tord, mais pas totalement raison :-)
En gros avec mon patch si tu utilises juste --pid sans argument ou --pid=$$, le message sera toujours reçu !
Par contre si tu utilises MAINPID= ou rien tu as 99% de chance que le message soit perdu.

En résumé, systemd-notify doit toujours être appelé avec l'option --pid avec ou sans valeur associée

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 17:11
par cycyx
Donc, si je comprends bien, pour que cela fonctionne, il faudrait que systemd-notify utilise *toujours* le PID de son père (même avec NotifyAccess=all dans le unit file), car de toute façon cela ne fonctionne pas sans ça, non ?

Donc pourquoi avoir créé cette option à la base ? Ou MAINPID ? En cas de processus fils qui crée un processus fils qui appelle lui-même systemd-notify ?

Bon, je n'ai plus qu'à recompiler systemd moi, ça m'enchante ! :p

Et merci.

Maintenant si j'arrivais à comprendre les dépendances dans systemd (voir mon autre post), ce serait parfait ! :D

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 18:13
par benjarobin
Attention le PID du père de systemd-notify n'est pas forcément le PID du service...

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 20:08
par cycyx
C'est pas faux, mais le résultat est le même : systemd-notify fournit tel quel est inutilisable (et probablement depuis plusieurs années...).

Re: [systemd-notify] Impossible à utiliser

Publié : sam. 19 sept. 2015, 22:06
par benjarobin
Je revient sur la chose, j'avais un peu de temps ce soir... J'avais mal compris le sens de MAINPID et je crains que toi aussi. Le but de --pid ou de MAINPID est juste d'indiquer à systemd que le processus principal d'un service est celui spécifié. J'ai compris ceci en regardant le code très en détail, mais en faites c'était très clairement indiqué dans la doc...

Le problème de systemd-notify, qui n'a surement jamais vraiment fonctionné, c'est qu'il envoi un message avec son identifiant (pid) et se termine de suite. Quand systemd reçoit le message il ne reconnait pas ce pid car il n'existe déjà plus. Donc un gros correctif à été réalisé ici https://bugs.freedesktop.org/show_bug.cgi?id=75680 mais qui a été cassé par quelqu'un par la suite (le but de mon premier patch). Sauf que le correctif du rapport de bug n'avait en effet pas corrigé entièrement le problème de systemd-notify qui n’envoie pas dans tous les cas un pid non nul (surement le sens de tes derniers messages...)
Bref j'ai donc soumis un dernier patch