fix(livraison) : la pose remplace un binaire en service #15

Merged
foXaCe merged 3 commits from fix/pose-binaire-en-service into main 2026-10-17 16:12:42 +02:00
Owner

Le defaut

La deuxième livraison du 108 a échoué, alors que la première avait réussi :

failed to create file: /opt/pcmirror-serveur/pcmirror-serveur: Text file busy
CAUSE : somme différente après copie (reçu 5c2bc7a8f1f7, attendu 128c8abdfbd4)

La pose écrasait le fichier en place — ce qu'un binaire en cours d'exécution
refuse (Text file busy, ETXTBSY). Autrement dit : la livraison ne pouvait plus
remplacer le service qu'elle venait elle-même de poser. Comme le comportement
est intermittent (la n°64 a réussi), la chaîne échouait tantôt, réussissait
tantôt, sans rien dire de solide.

C'est le contrôle de somme, ajouté justement pour ça, qui a empêché la
livraison d'annoncer un succès sans rien changer.

Le correctif

Les trois transports passent par un nom temporaire puis un renommage —
jamais par une écriture sur le fichier en place :

transport avant après
local install sur la destination install sur .neuf, puis mv -f
ssh install sur la destination scp sur .neuf, puis mv -f
pve pct push sur la destination pct push sur .neuf, puis mv -f

Seul pve était fautif en pratique (pct push écrit directement) ; local et
ssh s'en remettaient à install, qui supprime avant de créer. Autant ne pas
s'en remettre à un détail d'implémentation : le renommage marche pour les trois,
et il est maintenant explicite et commenté sur place.

Le retour arrière renomme lui aussi, pour la même raison.

Vérifications

  • Reproduit : le transport pve rejoué sur le 108 avec le service en
    marche, avec le code d'avant → Text file busy, code de sortie 1.
  • Corrigé : la même pose, même 108, service en marche → succès, contrôle de
    santé « bonne », code de sortie 0.
  • L'essai à blanc verrouille l'invariant avec un vrai ELF mis en marche dans
    le bac. Un script ne suffirait pas : le noyau ne le protège pas de l'écriture.
    Il ne couvre que le transport local — pve ne se prouve que sur un vrai
    conteneur, ce qui a été fait ci-dessus.
  • Essai complet : 56 essais verts ; shellcheck -S warning muet.

À noter

Ce correctif a été trouvé en faisant la première pose du 108 (elle est faite :
mirror-status.service arrêté, pcmirror-serveur.service en place et sain) puis
en laissant la CI livrer par-dessus. C'est la livraison n°64 qui a posé la
première version, et la n°62 qui a révélé ce défaut.

## Le defaut La **deuxième** livraison du 108 a échoué, alors que la première avait réussi : ``` failed to create file: /opt/pcmirror-serveur/pcmirror-serveur: Text file busy CAUSE : somme différente après copie (reçu 5c2bc7a8f1f7, attendu 128c8abdfbd4) ``` La pose écrasait le fichier en place — ce qu'un binaire **en cours d'exécution** refuse (`Text file busy`, ETXTBSY). Autrement dit : la livraison ne pouvait plus remplacer le service qu'elle venait elle-même de poser. Comme le comportement est intermittent (la n°64 a réussi), la chaîne échouait tantôt, réussissait tantôt, sans rien dire de solide. C'est le contrôle de somme, ajouté justement pour ça, qui a empêché la livraison d'annoncer un succès sans rien changer. ## Le correctif Les trois transports passent par un **nom temporaire puis un renommage** — jamais par une écriture sur le fichier en place : | transport | avant | après | | --- | --- | --- | | `local` | `install` sur la destination | `install` sur `.neuf`, puis `mv -f` | | `ssh` | `install` sur la destination | `scp` sur `.neuf`, puis `mv -f` | | `pve` | `pct push` sur la destination | `pct push` sur `.neuf`, puis `mv -f` | Seul `pve` était fautif en pratique (`pct push` écrit directement) ; `local` et `ssh` s'en remettaient à `install`, qui supprime avant de créer. Autant ne pas s'en remettre à un détail d'implémentation : le renommage marche pour les trois, et il est maintenant explicite et commenté sur place. Le **retour arrière** renomme lui aussi, pour la même raison. ## Vérifications - **Reproduit** : le transport `pve` rejoué sur le 108 avec le service en marche, avec le code d'avant → `Text file busy`, code de sortie 1. - **Corrigé** : la même pose, même 108, service en marche → succès, contrôle de santé « bonne », code de sortie 0. - L'essai à blanc verrouille l'invariant avec un **vrai ELF** mis en marche dans le bac. Un script ne suffirait pas : le noyau ne le protège pas de l'écriture. Il ne couvre que le transport `local` — `pve` ne se prouve que sur un vrai conteneur, ce qui a été fait ci-dessus. - Essai complet : **56 essais verts** ; `shellcheck -S warning` muet. ## À noter Ce correctif a été trouvé **en faisant la première pose du 108** (elle est faite : `mirror-status.service` arrêté, `pcmirror-serveur.service` en place et sain) puis en laissant la CI livrer par-dessus. C'est la livraison n°64 qui a posé la première version, et la n°62 qui a révélé ce défaut.
fix(livraison) : la pose remplace un binaire en service
Some checks failed
Contrôles des références / Références du comportement (pull_request) Successful in 3s
Contrôles des références / Crate pcmirror (formatage, Clippy, tests) (pull_request) Failing after 44s
Contrôles des références / Livraison (style des scripts, essai à blanc) (pull_request) Successful in 3s
Contrôles des références / Front d'état (types, lint, format, tests, build, bout en bout) (pull_request) Successful in 37s
1b96f72989
La deuxième livraison du 108 a échoué, et la première avait réussi : la pose
écrasait le fichier en place, ce qu'un binaire **en cours d'exécution** refuse
(`Text file busy`, ETXTBSY). Autrement dit, la livraison ne pouvait plus
remplacer le service qu'elle venait de poser — et, le comportement étant
intermittent, elle échouait tantôt, réussissait tantôt, sans rien dire de solide.

Vu deux fois en vrai : la livraison n°62 est morte sur
`somme différente après copie (reçu 5c2bc7a8f1f7, attendu 128c8abdfbd4)`, et le
transport `pve` a été reproduit à la main, service en marche, avec la même
erreur.

Les trois transports passent maintenant par un nom temporaire puis un
renommage — jamais par une écriture sur le fichier en place. Le §pve était le
seul fautif (`pct push` écrit directement) ; `local` et `ssh` s'en remettaient à
`install`, qui supprime avant de créer. Autant ne pas s'en remettre à un détail
d'implémentation : le renommage est ce qui marche pour les trois, et il est
maintenant explicite.

Le retour arrière renomme lui aussi, pour la même raison.

L'essai à blanc verrouille l'invariant avec un **vrai ELF** mis en marche dans
le bac — un script ne suffirait pas, le noyau ne le protège pas de l'écriture
(les trois transports ne se vérifient là que pour `local` ; `pve` ne se prouve
que sur un vrai conteneur, ce qui a été fait).

Vérifié : l'essai passe (56 essais), et la pose, rejouée sur le 108 avec le
service en marche, réussit là où le code d'avant échouait.
Collaborator

fusion-auto : pas de fusion, la CI est rouge (Crate pcmirror). Le chef de l'atelier renvoie la carte à l'agent ; l'étiquette tombera d'elle-même une fois corrigé.

`fusion-auto` : pas de fusion, la CI est rouge (Crate pcmirror). Le chef de l'atelier renvoie la carte à l'agent ; l'étiquette tombera d'elle-même une fois corrigé.
test(pc-mirror) : le banc n'exige plus « aucun rsync » sur la machine
Some checks failed
Contrôles des références / Références du comportement (pull_request) Successful in 3s
Contrôles des références / Crate pcmirror (formatage, Clippy, tests) (pull_request) Failing after 1m20s
Contrôles des références / Livraison (style des scripts, essai à blanc) (pull_request) Successful in 3s
Contrôles des références / Front d'état (types, lint, format, tests, build, bout en bout) (pull_request) Successful in 36s
d408844388
`etat_json_complet` affirmait `sync_en_cours == false`, avec pour raison « aucun
rsync ne tourne ici ». Or ce champ décrit l'état de la machine, et le poste lance
un rsync horaire pour le miroir : le job Rust de la CI échouait donc **une fois
par heure**, pendant les minutes que durait la synchro. C'est bien ce qui a fait
échouer la CI de cette branche, alors qu'elle ne touche que la livraison — et ce
qui l'avait déjà fait échouer plus tôt dans la journée.

Le banc exige maintenant la cohérence : le JSON dit ce que la machine dit au même
instant. La détection se prouve là où elle vit — `telemetrie` — avec un faux
`rsync` que le banc maîtrise (un binaire portant ce nom, lancé et arrêté par le
test), au lieu du « l'appel ne panique pas » d'avant, qui ne vérifiait rien.

Vérifié : 195 tests verts, avec et sans `frontend/dist` ; Clippy muet.
test(pc-mirror) : un lien, pas une copie, pour le faux rsync
All checks were successful
Contrôles des références / Références du comportement (pull_request) Successful in 3s
Contrôles des références / Crate pcmirror (formatage, Clippy, tests) (pull_request) Successful in 1m18s
Contrôles des références / Livraison (style des scripts, essai à blanc) (pull_request) Successful in 3s
Contrôles des références / Front d'état (types, lint, format, tests, build, bout en bout) (pull_request) Successful in 37s
e96d52c23d
Le banc écrivait un binaire puis l'exécutait aussitôt : le noyau répond
« Text file busy » (`ExecutableFileBusy`) — la course est tombée du premier coup
sur la CI, alors qu'elle ne se voit presque jamais en local (15 passes sur 15).

Un lien symbolique nommé `rsync` vers `sleep` suffit, et rien n'est écrit :
`/proc/<pid>/comm` vaut bien `rsync`, ce que la détection regarde.

Vérifié : 195 tests verts sans `frontend/dist` (la condition de la CI) et avec,
couverture 91,26 %, Clippy muet.
foXaCe merged commit 560840909d into main 2026-10-17 16:12:42 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
foXaCe/pc-mirror!15
No description provided.