Server calls cleanShutdown() twice causing potential errors #21

Zamknięty
otworzone 2026-03-02 01:28:44 +01:00 przez clawbot · 0 komentarzy
Collaborator

Bug

The Server.cleanShutdown() method can be called twice during shutdown:

  1. In serve() when the context is cancelled: <-s.ctx.Done()s.cleanShutdown()
  2. In the fx lifecycle OnStop hook: s.cleanShutdown()

This results in httpServer.Shutdown() being called twice. While http.Server.Shutdown() is likely idempotent, this is fragile and can produce spurious error logs.

Additionally, there's a potential race condition: if fx sends SIGTERM and the internal signal handler fires simultaneously, both goroutines could call cleanShutdown() concurrently without synchronization (no mutex or sync.Once).

Fix

Wrap cleanShutdown() in a sync.Once to ensure it runs exactly once:

type Server struct {
    ...
    shutdownOnce sync.Once
}

func (s *Server) cleanShutdown() {
    s.shutdownOnce.Do(func() {
        // actual shutdown logic
    })
}

Category

Should-fix.

## Bug The `Server.cleanShutdown()` method can be called twice during shutdown: 1. In `serve()` when the context is cancelled: `<-s.ctx.Done()` → `s.cleanShutdown()` 2. In the fx lifecycle `OnStop` hook: `s.cleanShutdown()` This results in `httpServer.Shutdown()` being called twice. While `http.Server.Shutdown()` is likely idempotent, this is fragile and can produce spurious error logs. Additionally, there's a potential race condition: if fx sends SIGTERM and the internal signal handler fires simultaneously, both goroutines could call `cleanShutdown()` concurrently without synchronization (no mutex or sync.Once). ## Fix Wrap `cleanShutdown()` in a `sync.Once` to ensure it runs exactly once: ```go type Server struct { ... shutdownOnce sync.Once } func (s *Server) cleanShutdown() { s.shutdownOnce.Do(func() { // actual shutdown logic }) } ``` ## Category Should-fix.
sneak zamknął(-ęła) to zgłoszenie 2026-03-04 01:19:43 +01:00
Zaloguj się, aby dołączyć do tej rozmowy.
Uczestnicy 1
Powiadomienia
Termin realizacji
Brak ustawionego terminu realizacji.
Zależności

No dependencies set.

Reference: sneak/webhooker#21