From 3353b3ae8208be6ec55bca8c3f5b99d451d9cedc Mon Sep 17 00:00:00 2001 From: Jacquin Antoine Date: Sun, 19 Apr 2026 14:24:50 +0200 Subject: [PATCH] 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 --- services/ja4ebpf/cmd/ja4ebpf/main.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/services/ja4ebpf/cmd/ja4ebpf/main.go b/services/ja4ebpf/cmd/ja4ebpf/main.go index 59aefa4..3551e6f 100644 --- a/services/ja4ebpf/cmd/ja4ebpf/main.go +++ b/services/ja4ebpf/cmd/ja4ebpf/main.go @@ -294,9 +294,19 @@ func main() { // --- 7. Goroutine : écriture des sessions prêtes --- go func() { - for s := range mgr.ReadyCh { - if w != nil { - w.Write(s) + for { + select { + case s, ok := <-mgr.ReadyCh: + if !ok { + // Canal fermé, terminer la goroutine + return + } + if w != nil { + w.Write(s) + } + case <-ctx.Done(): + // Context annulé, terminer la goroutine gracieusement + return } } }() @@ -323,9 +333,17 @@ func main() { case sig := <-sigCh: log.Printf("[ja4ebpf] signal reçu: %v — arrêt gracieux", sig) case <-ctx.Done(): + log.Printf("[ja4ebpf] contexte annulé — arrêt gracieux") } + // Annuler le contexte pour signaler toutes les goroutines 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é") }