Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: avoid race conditions #89

Merged
merged 1 commit into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions ap/ap.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type Accesspoint struct {
recvChans map[PacketType][]chan Packet
recvChansLock sync.RWMutex
lastPongAck time.Time
lastPongAckLock sync.Mutex

// connMu is held for writing when performing reconnection and for reading mainly when accessing welcome
// or sending packets. If it's not held, a valid connection (and APWelcome) is available. Be careful not to deadlock
Expand Down Expand Up @@ -263,7 +264,9 @@ loop:
}
case PacketTypePongAck:
log.Tracef("received accesspoint pong ack")
ap.lastPongAckLock.Lock()
ap.lastPongAck = time.Now()
ap.lastPongAckLock.Unlock()
continue
default:
ap.recvChansLock.RLock()
Expand Down Expand Up @@ -323,8 +326,11 @@ loop:
case <-ap.pongAckTickerStop:
break loop
case <-ticker.C:
if time.Since(ap.lastPongAck) > pongAckInterval {
log.Errorf("did not receive last pong ack from accesspoint, %.0fs passed", time.Since(ap.lastPongAck).Seconds())
ap.lastPongAckLock.Lock()
timePassed := time.Since(ap.lastPongAck)
ap.lastPongAckLock.Unlock()
if timePassed > pongAckInterval {
log.Errorf("did not receive last pong ack from accesspoint, %.0fs passed", timePassed.Seconds())

// closing the connection should make the read on the "recvLoop" fail,
// continue hoping for a new connection
Expand Down
12 changes: 10 additions & 2 deletions dealer/dealer.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Dealer struct {
recvLoopStop chan struct{}
recvLoopOnce sync.Once
lastPong time.Time
lastPongLock sync.Mutex

// connMu is held for writing when performing reconnection and for reading when accessing the conn.
// If it's not held, a valid connection is available. Be careful not to deadlock anything with this.
Expand Down Expand Up @@ -125,8 +126,11 @@ loop:
case <-d.pingTickerStop:
break loop
case <-ticker.C:
if time.Since(d.lastPong) > pingInterval+timeout {
log.Errorf("did not receive last pong from dealer, %.0fs passed", time.Since(d.lastPong).Seconds())
d.lastPongLock.Lock()
timePassed := time.Since(d.lastPong)
d.lastPongLock.Unlock()
if timePassed > pingInterval+timeout {
log.Errorf("did not receive last pong from dealer, %.0fs passed", timePassed.Seconds())

// closing the connection should make the read on the "recvLoop" fail,
// continue hoping for a new connection
Expand Down Expand Up @@ -199,7 +203,9 @@ loop:
// we never receive ping messages
break
case "pong":
d.lastPongLock.Lock()
d.lastPong = time.Now()
d.lastPongLock.Unlock()
log.Tracef("received dealer pong")
break
default:
Expand Down Expand Up @@ -266,7 +272,9 @@ func (d *Dealer) reconnect() error {
return err
}

d.lastPongLock.Lock()
d.lastPong = time.Now()
d.lastPongLock.Unlock()
// restart the recv loop
go d.recvLoop()

Expand Down
Loading