Skip to content

Fix BGReader deadlock when stopping background reads#2502

Closed
sergeydobrodey wants to merge 1 commit intojackc:masterfrom
sergeydobrodey:master
Closed

Fix BGReader deadlock when stopping background reads#2502
sergeydobrodey wants to merge 1 commit intojackc:masterfrom
sergeydobrodey:master

Conversation

@sergeydobrodey
Copy link

@sergeydobrodey sergeydobrodey commented Feb 10, 2026

BGReader.Read could block forever if Stop() was called while the background goroutine was stuck in a read.

Read now falls back to direct reading when status is StatusStopping, not just StatusStopped.
Adds a unit test that reproduces the deadlock and verifies the fix.

Tests
go test ./pgconn/internal/bgreader -run TestBGReaderReadDoesNotWaitWhenStopping

Possible it's a fix for #2119

@jackc
Copy link
Owner

jackc commented Feb 11, 2026

I think a race condition would be possible with this change. BGReader is defined as concurrency safe, but there is no guarantee the underlying io.Reader is. With this change the underlying io.Reader can be used concurrently.

  1. BGReader.Start() is called. bgRead() is started in a goroutine and blocks on Read() from the underlying io.Reader.
  2. BGReader.Read() is called and execution waits at r.cond.Wait()
  3. BGReader.Stop() is called. This sets status to StatusStopping, but it does not stop the goroutine running bgRead().
  4. BGReader.Read() is called again. Because status is StatusStopping it also calls Read() from the underlying io.Reader.

In practice, this shouldn't happen, both because we don't call BGReader.Read() concurrently, and we only use it with net.Conn which is concurrency safe. However, I don't want to introduce a latent bug either.

@sergeydobrodey
Copy link
Author

Agree. I'll close this PR

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.

2 participants