fix(main): prevent goroutine leak on shutdown

The ReadyCh consumer goroutine could block indefinitely during shutdown
because it only checked for channel closure but not context cancellation.

Changes:
- Add select statement to check both ctx.Done() and ReadyCh closure
- Add shutdown logging for better debugging
- Add 100ms grace period for goroutines to exit

Fixes potential hangs when receiving SIGTERM/SIGINT.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jacquin Antoine
2026-04-19 14:24:50 +02:00
parent 8beed18eea
commit 3353b3ae82

View File

@ -294,10 +294,20 @@ func main() {
// --- 7. Goroutine : écriture des sessions prêtes --- // --- 7. Goroutine : écriture des sessions prêtes ---
go func() { go func() {
for s := range mgr.ReadyCh { for {
select {
case s, ok := <-mgr.ReadyCh:
if !ok {
// Canal fermé, terminer la goroutine
return
}
if w != nil { if w != nil {
w.Write(s) w.Write(s)
} }
case <-ctx.Done():
// Context annulé, terminer la goroutine gracieusement
return
}
} }
}() }()
@ -323,9 +333,17 @@ func main() {
case sig := <-sigCh: case sig := <-sigCh:
log.Printf("[ja4ebpf] signal reçu: %v — arrêt gracieux", sig) log.Printf("[ja4ebpf] signal reçu: %v — arrêt gracieux", sig)
case <-ctx.Done(): case <-ctx.Done():
log.Printf("[ja4ebpf] contexte annulé — arrêt gracieux")
} }
// Annuler le contexte pour signaler toutes les goroutines
cancel() cancel()
log.Printf("[ja4ebpf] contexte annulé, attente de la fermeture des goroutines...")
// Attendre un court instant pour que les goroutines se terminent
// Le defer mgr.Close() fermera ReadyCh, ce qui débloquera la goroutine d'écriture
time.Sleep(100 * time.Millisecond)
log.Printf("[ja4ebpf] arrêt terminé") log.Printf("[ja4ebpf] arrêt terminé")
} }