Skip to content

Commit c0baba6

Browse files
committed
fix race
1 parent 7af418a commit c0baba6

File tree

1 file changed

+21
-1
lines changed

1 file changed

+21
-1
lines changed

internal/pool/conn.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88
"net"
9+
"sync"
910
"sync/atomic"
1011
"time"
1112

@@ -33,6 +34,10 @@ type Conn struct {
3334
bw *bufio.Writer
3435
wr *proto.Writer
3536

37+
// Lightweight mutex to protect reader operations during handoff
38+
// Only used for the brief period during SetNetConn and HasBufferedData/PeekReplyTypeSafe
39+
readerMu sync.RWMutex
40+
3641
Inited bool
3742
pooled bool
3843
createdAt time.Time
@@ -319,7 +324,13 @@ func (cn *Conn) ExecuteInitConn(ctx context.Context) error {
319324
func (cn *Conn) SetNetConn(netConn net.Conn) {
320325
// Store the new connection atomically first (lock-free)
321326
cn.setNetConn(netConn)
327+
328+
// Protect reader reset operations to avoid data races
329+
// Use write lock since we're modifying the reader state
330+
cn.readerMu.Lock()
322331
cn.rd.Reset(netConn)
332+
cn.readerMu.Unlock()
333+
323334
cn.bw.Reset(netConn)
324335
}
325336

@@ -393,20 +404,29 @@ func (cn *Conn) Rd() *proto.Reader {
393404
}
394405

395406
// Reader returns the connection's proto reader for processing notifications
407+
// Note: This method should be used carefully as it returns the raw reader.
408+
// For thread-safe operations, use HasBufferedData() and PeekReplyTypeSafe().
396409
func (cn *Conn) Reader() *proto.Reader {
397410
return cn.rd
398411
}
399412

400413
// HasBufferedData safely checks if the connection has buffered data.
401414
// This method is used to avoid data races when checking for push notifications.
402415
func (cn *Conn) HasBufferedData() bool {
416+
// Use read lock for concurrent access to reader state
417+
cn.readerMu.RLock()
418+
defer cn.readerMu.RUnlock()
403419
return cn.rd.Buffered() > 0
404420
}
405421

406422
// PeekReplyTypeSafe safely peeks at the reply type.
407423
// This method is used to avoid data races when checking for push notifications.
408424
func (cn *Conn) PeekReplyTypeSafe() (byte, error) {
409-
if !cn.HasBufferedData() {
425+
// Use read lock for concurrent access to reader state
426+
cn.readerMu.RLock()
427+
defer cn.readerMu.RUnlock()
428+
429+
if cn.rd.Buffered() <= 0 {
410430
return 0, fmt.Errorf("redis: can't peek reply type, no data available")
411431
}
412432
return cn.rd.PeekReplyType()

0 commit comments

Comments
 (0)