Server calls cleanShutdown() twice causing potential errors #21

Closed
opened 2026-03-02 01:28:44 +01:00 by clawbot · 0 comments
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.
clawbot added the
bot
label 2026-03-02 01:28:44 +01:00
sneak closed this issue 2026-03-04 01:19:43 +01:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: sneak/webhooker#21
No description provided.