Il se passe parfois des choses bizarres. En mission pour un client j’intégrais son logiciel embarqué pour un dispositif médical. La carte principale est reliée aux différents moteurs et capteurs via des liens séries principalement, et à un autre module d’affichage via USB.
Justement, un ingénieur a remarqué que parfois, l’écran se fige en blanc quelques secondes après le démarrage. Il faut redémarrer pour que le produit se lance correctement. Au début on y a pas prété attention, mais bientôt j’ai remarqué le même disfonctionnement.
C’est bizarre, on s’est basés sur un produit existant, les changements matériels sont vraiment minimes, et les traces sur la console getty ne sont pas très parlantes. Elles ne disent rien en fait. On voit le bootloader qui nous fait son petit coucou, le linux qui démarre, puis qui passe la main à des applications en espace utilisateur, et puis ça bloque.
Ça a l’air d’être freezé. Mais j’ai beau mettre les traces noyau au maximum, on ne perçoit aucun message anormal. Que faire ? Ben déjà tester à la main, c’est long et fastidieux, mais je mesure que le problème apparait aléatoirement tous les 20 démarrages environs.
5% d’erreur dirons-nous, sur un produit qui est sensé rester allumé et tourner de nombreux mois, voire plusieurs années sans s’arrêter ce n’est pas forcément grave d’un point de vue fonctionnel… car si par malheur il se bloque, c’est dans les 10 premières secondes, l’utilisateur peut se dire qu’il y a eu un petit problème technique… il relance et tout marche.
Mais la Direction, n’est pas de cet avis. On ne sortira pas le produit avec ce problème. Soit. Mais maintenant il faut trouver une solution. Et avant tout la cause du problème. Et même plus important encore, une manière de tester que la solution envisagée résout bien le problème. Bref que même si on redémarre 1000 ou 10000 fois, on ne voit pas le soucis.
Ça je ne vais pas le faire à la main. Mais comment faire, alors que justement, quand les 10 premières secondes au démarrage se passent bien, le système n’a aucune raison de redémarrer. Et qu’au contraire, quand ça plante, on a aucun moyen automatique pour le remarquer, vu que le système est complètement bloqué ?
La solution a être la suivante: écrire un petit script lancé au tout début des services applicatifs, qui va incrémenter un compteur dont la valeur est affichée sur le getty et stockée dans la mémoire persistante. Et enclencher un redémarrage une fois qu’une vingtaine de secondes se sont écoulées, ce qui correspond au fait que le dernier service applicatif a été lancé dans notre cas.
Sur un système muni non pas du gestionnaire de services Systemd (qui est la norme actuellement), mais d’un simple SysV, cela se réalise en ajoutant une ligne à la fin du fichier /etc/inittab:
::sysinit:/sbin/reboot
Et voilà, tout simplement, le tour est joué. Le système assez minimal utilisé n’a pas de « runlevel », donc les deux premiers champs (avant les deux points et juste après) peuvent être laissés vides. Puis vient « sysinit », qui indique que l’action suivante doit être réalisée durant l’initialisation du système. Comme la ligne est mise à la fin du fichier, cette action sera réalisée après les autres commandes d’initialisation.
Et enfin la commande, on demande au système de redémarrer. Donc bilan des courses, on peut allumer le dispositif: sur l’écran console nous verrons les traces de démarrage, ainsi que le numéro de redémarrage. Le système va redémarrer en boucle, jusqu’à ce qu’il se bloque dans le cas où le disfonctionnement a lieu. À ce moment là, nous pouvons voir au bout de combien de redémarrages cela s’est produit, et mettre à jour les statistiques.
Si le système redémarre toujours au bout de plusieurs jours sans intervention humaine, c’est que le problème initial a été résolu. Mais ça, quel était le problème, quelle solution a été apportée, c’est une autre histoire 😉