From 7b9a9f5962bb5f6ff5dbbb28ab5ec9a17583cf01 Mon Sep 17 00:00:00 2001 From: harshitsinghbhandari <24b4506@iitb.ac.in> Date: Sun, 31 May 2026 20:25:56 +0530 Subject: [PATCH] fix(backend): drain reaper + cdc poller when startSession fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If startSession returned an error, run() returned immediately and the reaper + cdc poller goroutines kept running while defer store.Close() fired — a data race against the SQLite handle. Mirror the bottom-of-run shutdown sequence on the error path (cancel ctx, drain reaper, drain poller) so both goroutines have exited before the store is closed. The explicit-not-defer ordering is the same the existing post-srv.Run shutdown block uses; piling on more defers would hit the LIFO trap the same comment already warns about. Reported by Greptile on PR #52. Co-Authored-By: Claude Opus 4.7 --- backend/main.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/backend/main.go b/backend/main.go index b714e69ac..9fdb7a5e5 100644 --- a/backend/main.go +++ b/backend/main.go @@ -87,6 +87,16 @@ func run() error { // surfacing — so we hold the SM in a local until it does. sStack, err := startSession(ctx, cfg, lcStack, log) if err != nil { + // startSession is the first start* call after this point that can + // realistically fail while the cdc poller and the reaper are already + // running. Mirror the bottom-of-run shutdown sequence so both have + // drained before the deferred store.Close() fires. Defers would hit + // the LIFO trap (see comment after srv.Run), hence explicit. + stop() + lcStack.Stop() + if cdcErr := cdcPipe.Stop(); cdcErr != nil { + log.Error("cdc pipeline shutdown", "err", cdcErr) + } return err } _ = sStack