fix: incorrect reconnect logic that causes blocking when dialing connections

This commit is contained in:
Toby 2024-01-26 11:49:19 -08:00
parent e648321b96
commit 84b54eb702

View file

@ -58,52 +58,60 @@ func (rc *reconnectableClientImpl) reconnect() error {
func (rc *reconnectableClientImpl) TCP(addr string) (net.Conn, error) { func (rc *reconnectableClientImpl) TCP(addr string) (net.Conn, error) {
rc.m.Lock() rc.m.Lock()
defer rc.m.Unlock()
if rc.closed { if rc.closed {
rc.m.Unlock()
return nil, coreErrs.ClosedError{} return nil, coreErrs.ClosedError{}
} }
if rc.client == nil { if rc.client == nil {
// No active connection, connect first // No active connection, connect first
if err := rc.reconnect(); err != nil { if err := rc.reconnect(); err != nil {
rc.m.Unlock()
return nil, err 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 { if _, ok := err.(coreErrs.ClosedError); ok {
// Connection closed, reconnect // Connection closed, set client to nil for reconnect next time
if err := rc.reconnect(); err != nil { rc.m.Lock()
return nil, err // In case the client has already been reconnected by another goroutine
if rc.client == client {
rc.client = nil
} }
return rc.client.TCP(addr) rc.m.Unlock()
} else {
// OK or some other temporary error
return conn, err
} }
return conn, err
} }
func (rc *reconnectableClientImpl) UDP() (HyUDPConn, error) { func (rc *reconnectableClientImpl) UDP() (HyUDPConn, error) {
rc.m.Lock() rc.m.Lock()
defer rc.m.Unlock()
if rc.closed { if rc.closed {
rc.m.Unlock()
return nil, coreErrs.ClosedError{} return nil, coreErrs.ClosedError{}
} }
if rc.client == nil { if rc.client == nil {
// No active connection, connect first // No active connection, connect first
if err := rc.reconnect(); err != nil { if err := rc.reconnect(); err != nil {
rc.m.Unlock()
return nil, err return nil, err
} }
} }
conn, err := rc.client.UDP() client := rc.client
rc.m.Unlock()
conn, err := client.UDP()
if _, ok := err.(coreErrs.ClosedError); ok { if _, ok := err.(coreErrs.ClosedError); ok {
// Connection closed, reconnect // Connection closed, set client to nil for reconnect next time
if err := rc.reconnect(); err != nil { rc.m.Lock()
return nil, err // In case the client has already been reconnected by another goroutine
if rc.client == client {
rc.client = nil
} }
return rc.client.UDP() rc.m.Unlock()
} else {
// OK or some other temporary error
return conn, err
} }
return conn, err
} }
func (rc *reconnectableClientImpl) Close() error { func (rc *reconnectableClientImpl) Close() error {