Skip to content

main: bound GracefulStop so a hung stream cannot cost the access-state save - #73

Merged
shreyas-blacksmith merged 1 commit into
patchsetfrom
devin/1793636369-bounded-graceful-stop
Nov 2, 2026
Merged

shreyas-blacksmith merged 1 commit into
patchsetfrom
devin/1793636369-bounded-graceful-stop

Conversation

@shreyas-blacksmith

@shreyas-blacksmith shreyas-blacksmith commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

On bazel-l1-staging-2 (.17) a systemctl stop hung after Stopping gRPC server: grpcServer.GracefulStop() never returned, systemd SIGKILLed the process at TimeoutStopSec=30, and SaveAccessState (#72) never ran. GracefulStop waits for every in-flight stream to end and the fork sets no server keepalive, so a single stream whose client has gone away without closing it holds the drain forever. Traffic at the time was a trickle (one completed read in the 17 s before the signal), so this is a stuck stream, not load.

stopGrpcServer(s, grpcGracefulStopTimeout) replaces the bare call in the signal handler:

go func() { s.GracefulStop(); close(drained) }()
select {
case <-drained:
case <-time.After(10 * time.Second):
    log.Printf("gRPC server did not drain within %s, closing remaining connections", timeout)
    s.Stop()   // closes remaining transports; the pending GracefulStop returns
    <-drained
}

Idle or quickly-drained servers behave exactly as before (the second staging restart drained in ~1 s and saved/restored 14,901 entries). Only a drain that outlives 10 s is cut short, and the shutdown then still reaches the access-state save and the LRU observation drain well inside TimeoutStopSec.

Tests: TestStopGrpcServerBoundsAHungStream opens a bidi stream whose handler blocks until its context ends and asserts stopGrpcServer returns after the bound; TestStopGrpcServerReturnsEarlyWhenIdle covers the no-op path. Both run under -race.

Link to Devin session: https://app.devin.ai/sessions/df6c6655558146b9bafe936b062e49e7
Open in Devin Desktop: https://app.devin.ai/desktop/session/df6c6655558146b9bafe936b062e49e7?variant=devin
Requested by: @shreyas-blacksmith


Run Proof on this PR
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

…e save

One in-flight gRPC stream whose client has gone away held GracefulStop past
systemd's TimeoutStopSec on a staging L1; the SIGKILL that followed skipped
SaveAccessState. Drain for at most 10s, then Stop() the remaining
connections so shutdown always reaches the save.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@blacksmith-staging

blacksmith-staging Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Matches Hung gRPC stream no longer blocks shutdown

Before, the server never left GracefulStop and was SIGKILLed at 30 s with no access state saved. After, it closed the hung stream at 10 s, stopped gRPC, saved access state, and exited 0.

Merge-base

Hung stream, before

This PR ff9311e3

Hung stream, after

Also checked · 2 not run

Not run Idle server stops as before · Not run
Not run Drain inside the bound is not cut short · Not run

Proof on ff9311e3 · ended early (interrupted)

View full Proof report

@shreyas-blacksmith
shreyas-blacksmith merged commit 5ebdb31 into patchset Nov 2, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant