Bonjour la liste,
Je rencontre un bug des plus étranges dans un script bash. Le script effectue
des traitements en parallèle. La fin des processus fils est vérifiée par
polling¹ avec kill -0. Je récupère ensuite le statut avec wait :
(Code complet :
https://forge.riquer.fr/p/AtOM/source/tree/master/lib/workers/check et
https://forge.riquer.fr/p/AtOM/source/tree/master/lib/workers/destroy)
checkworkers() {
for key in ${!workers[@]} # workers est un tableau listant les PID des
# traitements en cours
do
if ! kill -0 ${workers[key]} 2>/dev/null
then
if wait ${workers[key]}
then
# Youpi
else
# Oops
fi
fi
done
}
Ça marche très bien 4999 fois sur 5000, mais de temps en temps, wait ne rend
pas la main, alors que le PID en question n'existe plus (n'apparaît pas dans
(h)top, /proc/$PID n'existe pas, …). J'ai vérifié avec strace, Bash est bloqué
sur waitpid(…).
Je suis à la fois incapable de montrer que c'est un bug dans bash ou la libc
et incapable de trouver une quelconque cause dans mon code (si le process
n'existe pas, waitpid() *doit* rendre la main – ou alors j'ai pas compris).
Si vous avez des solutions, des idées d'autres tests à faire, ou juste si vous
avez déjà rencontré le même souci, je suis preneur.
Versions:
$ dpkg -l bash libc6 linux-image-*|grep ii
ii bash 4.2+dfsg-0.1 amd64 GNU Bourne Again SHell
ii libc6:amd64 2.17-93 amd64 Embedded GNU C Library:
Shared libraries
ii linux-image-3.2.0-4-rt-amd64 3.2.51-1 amd64 Linux 3.2 for 64-bit PCs,
PREEMPT_RT
¹ J'avais d'abord tenté d'utiliser des signaux, mais me suis heurté au fait
que malloc() soit interdit dans ce contexte.