mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
Le verrou de l'optimiseur ne doit jamais bloquer quand aucune optimisation ne tourne, et ne jamais passer pour périmé quand elle tourne. Plusieurs identités de processus ne tenaient pas ces deux promesses hors Windows. - Linux : l'instant de démarrage est relatif au boot. Après une coupure, un service relancé au même moment du démarrage retrouvait PID et top : le verrou de l'ancien passait pour vivant et tout était refusé jusqu'à son retrait à la main. L'identifiant du boot le préfixe ; un verrou qui porte notre PID sans être l'un des nôtres est périmé. - Linux : un binaire remplacé par une mise à jour (« (deleted) ») faisait passer le propriétaire vivant pour mort. La mise à jour est de toute façon refusée pendant une optimisation (interface et loki update). - macOS : ps rend lstart dans la langue et le fuseau de l'appelant ; le web (launchd) et un terminal en français ne lisaient pas la même identité. LC_ALL=C et TZ=UTC. - Un verrou illisible tout juste créé (vide entre création et écriture) n'est plus retiré : seulement après 10 s. - loki tune : terminal fermé ou kill (SIGTERM, SIGHUP) annulent proprement, comme Ctrl-C ; Ctrl-C retrouve son sens aux questions de fin. - Application : la sauvegarde est notée dans le verrou ; un Loki tué avant la vérification remet l'ancienne version au redémarrage. Deux clics rapprochés ne lancent plus deux applications. Un échec de relance du vrai moteur se voit dans le résultat, plus seulement au journal ; un essai qui survit à son arrêt reste noté dans le verrou. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
53 lines
1.8 KiB
Go
53 lines
1.8 KiB
Go
//go:build linux
|
|
|
|
package loki
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// procIdentity : instant de démarrage (en tops d'horloge depuis le boot, champ
|
|
// 22 de /proc/<pid>/stat) et binaire d'un processus vivant. Un PID recyclé
|
|
// après un redémarrage de Loki a un autre instant de démarrage : l'optimiseur ne
|
|
// tue un essai orphelin que si les deux concordent (backend_tune_lock.go).
|
|
//
|
|
// L'instant est relatif au boot : après une coupure de courant, un service
|
|
// lancé au même moment du démarrage peut retrouver le même PID ET le même top,
|
|
// et un verrou laissé par l'ancien passerait pour vivant — tout serait refusé
|
|
// jusqu'à son retrait à la main. L'identifiant du boot le préfixe donc.
|
|
func procIdentity(pid int) (start, exe string, ok bool) {
|
|
if pid <= 0 {
|
|
return "", "", false
|
|
}
|
|
b, err := os.ReadFile("/proc/" + strconv.Itoa(pid) + "/stat")
|
|
if err != nil {
|
|
return "", "", false
|
|
}
|
|
// Le nom du processus (champ 2, entre parenthèses) peut contenir des blancs
|
|
// et des parenthèses : on repart de la DERNIÈRE parenthèse fermante.
|
|
s := string(b)
|
|
i := strings.LastIndexByte(s, ')')
|
|
if i < 0 {
|
|
return "", "", false
|
|
}
|
|
f := strings.Fields(s[i+1:])
|
|
// f[0] est le champ 3 (état) : le champ 22 est donc f[19]. Un zombie a fini
|
|
// de tourner, il ne compte plus comme vivant.
|
|
if len(f) < 20 || f[0] == "Z" {
|
|
return "", "", false
|
|
}
|
|
exe, _ = os.Readlink("/proc/" + strconv.Itoa(pid) + "/exe")
|
|
// Binaire remplacé par une mise à jour pendant que le processus tourne : le
|
|
// lien porte « (deleted) », c'est pourtant bien le même processus.
|
|
exe = strings.TrimSuffix(exe, " (deleted)")
|
|
start = f[19]
|
|
if b, err := os.ReadFile("/proc/sys/kernel/random/boot_id"); err == nil {
|
|
if id := strings.TrimSpace(string(b)); id != "" {
|
|
start = id + "/" + start
|
|
}
|
|
}
|
|
return start, exe, true
|
|
}
|