Skip to content

Commit 5f3a53f

Browse files
authored
fix: fix race condition in pubsub startup (#17088)
fixes coder/internal#525 If the context is canceled, the goroutine that is supposed to read from the `errCh` could exit prematurely, leading to a goroutine leak. Refactors this code so it cannot block.
1 parent 4c33846 commit 5f3a53f

File tree

1 file changed

+9
-8
lines changed

1 file changed

+9
-8
lines changed

coderd/database/pubsub/pubsub.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,6 @@ func (p *PGPubsub) startListener(ctx context.Context, connectURL string) error {
492492
p.connected.Set(0)
493493
// Creates a new listener using pq.
494494
var (
495-
errCh = make(chan error)
496495
dialer = logDialer{
497496
logger: p.logger,
498497
// pq.defaultDialer uses a zero net.Dialer as well.
@@ -525,6 +524,10 @@ func (p *PGPubsub) startListener(ctx context.Context, connectURL string) error {
525524
dc.Dialer(dialer)
526525
}
527526

527+
var (
528+
errCh = make(chan error, 1)
529+
sentErrCh = false
530+
)
528531
p.pgListener = pqListenerShim{
529532
Listener: pq.NewConnectorListener(connector, connectURL, time.Second, time.Minute, func(t pq.ListenerEventType, err error) {
530533
switch t {
@@ -541,18 +544,16 @@ func (p *PGPubsub) startListener(ctx context.Context, connectURL string) error {
541544
p.logger.Error(ctx, "pubsub failed to connect to postgres", slog.Error(err))
542545
}
543546
// This callback gets events whenever the connection state changes.
544-
// Don't send if the errChannel has already been closed.
545-
select {
546-
case <-errCh:
547+
// Only send the first error.
548+
if sentErrCh {
547549
return
548-
default:
549-
errCh <- err
550-
close(errCh)
551550
}
551+
errCh <- err // won't block because we are buffered.
552+
sentErrCh = true
552553
}),
553554
}
554555
select {
555-
case err := <-errCh:
556+
case err = <-errCh:
556557
if err != nil {
557558
_ = p.pgListener.Close()
558559
return xerrors.Errorf("create pq listener: %w", err)

0 commit comments

Comments
 (0)