mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 06:58:14 +02:00
Optimiseur : un « loki tune » tué par kill -9 ne laisse plus le moteur arrêté
Le verrou périmé n'était repris qu'au démarrage du processus web. Un « loki tune » en ligne de commande tué sans ses defers (kill -9, terminal perdu) laissait donc le vrai moteur arrêté — et peut-être l'essai en VRAM — jusqu'au prochain redémarrage de l'interface. - Le processus web refait la reprise toutes les 30 s, avec la même logique qu'au démarrage : essai orphelin arrêté (identité complète vérifiée), application interrompue défaite, moteur relancé seulement s'il tournait avant, ni sur un preset externe ni s'il est déjà reparti. - Coût : un stat par tic tant qu'aucun verrou n'existe ; pendant une optimisation vivante, la lecture du verrou et de l'identité de son propriétaire. Une seule goroutine, endormie sur le tic. - Test : relance au tic qui suit la mort du propriétaire, une fois ; rien sans verrou, rien pendant une optimisation vivante, rien pour un moteur qui ne tournait pas. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f0fef91773
commit
a325e98dad
4 files changed
+104
-10
No files matched your search
@@ -832,3 +832,68 @@ func TestTuneUndoInterruptedApply(t *testing.T) {
|
||||
t.Error("configuration modifiée hors phase d'application")
|
||||
}
|
||||
}
|
||||
|
||||
// Reprise dans le processus web : un « loki tune » tué sans ses defers ne
|
||||
// laisse plus le moteur arrêté jusqu'au prochain démarrage de l'interface. Le
|
||||
// tic suivant écarte le verrou périmé et relance le moteur — une fois, et
|
||||
// seulement s'il tournait avant. Sans verrou, ni lecture ni relance.
|
||||
func TestTuneRecoverWatch(t *testing.T) {
|
||||
testHome(t)
|
||||
alive := true
|
||||
prevAlive, prevStart := tuneProcAlive, tuneRecoverStart
|
||||
tuneProcAlive = func(p tuneProc) bool { return alive && p.PID == os.Getpid() }
|
||||
starts := 0
|
||||
tuneRecoverStart = func() { starts++ }
|
||||
t.Cleanup(func() { tuneProcAlive, tuneRecoverStart = prevAlive, prevStart })
|
||||
|
||||
tick := make(chan time.Time)
|
||||
done := make(chan struct{})
|
||||
go func() { tuneRecoverWatch(tick); close(done) }()
|
||||
// Un envoi est reçu quand le tic précédent a fini : deux de suite, et le
|
||||
// premier est traité en entier.
|
||||
step := func() { tick <- time.Now() }
|
||||
step()
|
||||
step()
|
||||
if starts != 0 {
|
||||
t.Fatal("relance sans verrou")
|
||||
}
|
||||
l, err := tuneLockAcquire("cli", true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
step()
|
||||
step()
|
||||
if starts != 0 {
|
||||
t.Fatal("relance pendant une optimisation vivante")
|
||||
}
|
||||
if _, err := os.Stat(tuneLockPath()); err != nil {
|
||||
t.Fatal("verrou vivant retiré")
|
||||
}
|
||||
alive = false // kill -9 : le verrou reste, son propriétaire est mort
|
||||
step()
|
||||
step()
|
||||
if starts != 1 {
|
||||
t.Fatalf("relances : %d, attendu 1", starts)
|
||||
}
|
||||
if _, err := os.Stat(tuneLockPath()); !os.IsNotExist(err) {
|
||||
t.Error("verrou périmé non retiré")
|
||||
}
|
||||
l.release()
|
||||
|
||||
// Le moteur ne tournait pas avant : verrou retiré, pas de relance.
|
||||
alive = true
|
||||
if _, err := tuneLockAcquire("cli", false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
alive = false
|
||||
step()
|
||||
step()
|
||||
close(tick)
|
||||
<-done
|
||||
if starts != 1 {
|
||||
t.Errorf("relance d'un moteur qui ne tournait pas : %d", starts)
|
||||
}
|
||||
if _, err := os.Stat(tuneLockPath()); !os.IsNotExist(err) {
|
||||
t.Error("verrou périmé non retiré")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user