Skip to content

Commit

Permalink
fix: incorrect reconnect logic that causes blocking when dialing conn…
Browse files Browse the repository at this point in the history
…ections
  • Loading branch information
tobyxdd committed Jan 26, 2024
1 parent e648321 commit 84b54eb
Showing 1 changed file with 26 additions and 18 deletions.
44 changes: 26 additions & 18 deletions core/client/reconnect.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,52 +58,60 @@ func (rc *reconnectableClientImpl) reconnect() error {

func (rc *reconnectableClientImpl) TCP(addr string) (net.Conn, error) {
rc.m.Lock()
defer rc.m.Unlock()
if rc.closed {
rc.m.Unlock()
return nil, coreErrs.ClosedError{}
}
if rc.client == nil {
// No active connection, connect first
if err := rc.reconnect(); err != nil {
rc.m.Unlock()
return nil, err
}
}
conn, err := rc.client.TCP(addr)
client := rc.client
rc.m.Unlock()

conn, err := client.TCP(addr)
if _, ok := err.(coreErrs.ClosedError); ok {
// Connection closed, reconnect
if err := rc.reconnect(); err != nil {
return nil, err
// Connection closed, set client to nil for reconnect next time
rc.m.Lock()
// In case the client has already been reconnected by another goroutine
if rc.client == client {
rc.client = nil
}
return rc.client.TCP(addr)
} else {
// OK or some other temporary error
return conn, err
rc.m.Unlock()
}
return conn, err
}

func (rc *reconnectableClientImpl) UDP() (HyUDPConn, error) {
rc.m.Lock()
defer rc.m.Unlock()
if rc.closed {
rc.m.Unlock()
return nil, coreErrs.ClosedError{}
}
if rc.client == nil {
// No active connection, connect first
if err := rc.reconnect(); err != nil {
rc.m.Unlock()
return nil, err
}
}
conn, err := rc.client.UDP()
client := rc.client
rc.m.Unlock()

conn, err := client.UDP()
if _, ok := err.(coreErrs.ClosedError); ok {
// Connection closed, reconnect
if err := rc.reconnect(); err != nil {
return nil, err
// Connection closed, set client to nil for reconnect next time
rc.m.Lock()
// In case the client has already been reconnected by another goroutine
if rc.client == client {
rc.client = nil
}
return rc.client.UDP()
} else {
// OK or some other temporary error
return conn, err
rc.m.Unlock()
}
return conn, err
}

func (rc *reconnectableClientImpl) Close() error {
Expand Down

0 comments on commit 84b54eb

Please sign in to comment.