mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 06:58:14 +02:00
Optimiseur : la reprise toutes les 30 s ne prend plus un verrou vivant pour périmé
Depuis que le processus web refait la reprise des optimisations interrompues toutes les 30 s, elle tourne pendant que ce même processus prend et rend ses propres verrous (bouton « Optimiser… », application d'un résultat). Trois fenêtres lui faisaient écarter un verrou bien vivant : le fichier créé avant l'inscription du verrou comme nôtre, l'inscription retirée avant le fichier (sous Windows, un fichier qu'un autre lit ne se supprime pas), et le renommage d'un verrou neuf pris entre la lecture et le ménage. En phase « application », le preset tout juste vérifié était alors défait, et le moteur relancé. - Inscription avant la création du fichier, retrait après lui ; un identifiant de prise (nonce) distingue deux verrous du même processus dans la même seconde. - Au moment de le rendre, le verrou est réécrit neutre (rien à défaire, rien à relancer, aucun essai), puis retiré avec quelques essais. - Le ménage relit ce qu'il vient de déplacer : un autre verrou, ou un verrou vivant, est remis en place par un lien (jamais par-dessus un verrou neuf). - La relance d'après reprise passe par serviceAction : une optimisation neuve qui a pris le verrou entre-temps garde le moteur arrêté. - Test : 60 prises et rendus en phase « application » sous une reprise en boucle, aucune relance ; échoue sur l'ancien code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c24472b91f
commit
5b834d54b2
2 files changed
+117
-9
No files matched your search
@@ -12,6 +12,7 @@ import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -957,3 +958,45 @@ func TestTuneForeignEngine(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// La reprise du processus web tourne toutes les 30 s, pendant que ce même
|
||||
// processus prend et rend ses propres verrous (bouton « Optimiser… »,
|
||||
// application d'un résultat). Elle ne doit jamais tenir l'un d'eux pour
|
||||
// périmé : entre la création du fichier et l'inscription, ou entre
|
||||
// l'inscription retirée et le fichier retiré, elle aurait défait un preset
|
||||
// tout juste vérifié (phase « application ») et relancé le moteur.
|
||||
func TestTuneRecoverNeverReapsOwnLock(t *testing.T) {
|
||||
testHome(t)
|
||||
prevAlive, prevStart := tuneProcAlive, tuneRecoverStart
|
||||
tuneProcAlive = func(p tuneProc) bool { return p.PID == os.Getpid() }
|
||||
var starts atomic.Int32
|
||||
tuneRecoverStart = func() { starts.Add(1) }
|
||||
t.Cleanup(func() { tuneProcAlive, tuneRecoverStart = prevAlive, prevStart })
|
||||
|
||||
stop := make(chan struct{})
|
||||
reaped := make(chan struct{})
|
||||
go func() {
|
||||
defer close(reaped)
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
return
|
||||
default:
|
||||
tuneRecoverStale()
|
||||
}
|
||||
}
|
||||
}()
|
||||
for i := 0; i < 60; i++ {
|
||||
l, err := tuneLockAcquire("apply", true)
|
||||
if err != nil {
|
||||
t.Fatalf("tour %d : %v", i, err)
|
||||
}
|
||||
l.setPhase("application")
|
||||
l.release()
|
||||
}
|
||||
close(stop)
|
||||
<-reaped
|
||||
if n := starts.Load(); n != 0 {
|
||||
t.Errorf("verrou vivant de ce processus écarté %d fois", n)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user