SIGTERM during startup panics on a nil httpServer, and cleanShutdown reads two fields with no happens-before edge #226
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found during the review of #218. Pre-existing on
next; NOT introduced or widened by that PR, which is why it was not blocking there.1. Nil dereference on an early SIGTERM.
s.httpServeris assigned inside theserveUntilShutdowngoroutine (internal/server/http.go:29), butcleanShutdowncallss.httpServer.Shutdown(ctxShutdown)unguarded (internal/server/server.go:236). A SIGTERM arriving between theOnStarthook returning and that assignment panics on a nil*http.Server.The window is not theoretical: it spans
configure()andenableSentry(), and the latter performs a networksentry.InitwhenSENTRY_DSNis set. A container killed early in a crash-loop or a fast redeploy lands in it.2. No happens-before edge on
s.httpServerands.sentryEnabled. On the SIGTERM path, and on a directapp.Stop(), those fields are written by the serve goroutine and read bycleanShutdownwith no synchronisation. The race detector has never flagged it because the existinginternal/servertests never callserve(). The path added by #218 IS race-free — the Shutdowner channel supplies the edge — which is precisely why-racestayed silent there.Not milestoned to 1.0: the impact is a non-graceful exit of a process that was already terminating, and steady-state operation is unaffected. Raising it here rather than folding it into the lifecycle work so it is not lost.
Definition of done:
cleanShutdownreadshttpServerandsentryEnabledunder a mutex, or behind a "server ready" handshakeapp.Stop()immediately afterapp.Start()and passes under-racestopTimeout/ShutdownTimeout/TailHookReservearithmetic pinned by #134 and #102 stays intactSeparately, and cheaply: nothing in the repo tests that the process exit STATUS is non-zero on listen failure — the test added by #218 asserts fx's
ShutdownSignal.ExitCode, not the process's. RewritingmainasStart/Done/Stopwould regress #200 silently with that test still green. Worth an exec-based assertion on the built binary.