fix(chain): Copy returns wrong pointer, connection leaks in Connect/Handshake, deferred cancel accumulation in retry loops
- transport.go: Copy() returned original pointer instead of the allocated copy, causing data races and incorrect routing for multiplexed chains. - route.go: Connect and Handshake failures in intermediate nodes leaked the returned connection. Handshake fix preserves the original Connect result (guaranteed non-nil) and closes both the Handshake return value and input. - router.go: defer cancel() inside retry loops accumulated context timers across iterations. Wrapped each loop body in an IIFE so defer scopes per-iteration and timers are released immediately.
This commit is contained in:
+10
-1
@@ -271,20 +271,29 @@ func (r *chainRoute) connect(ctx context.Context, logger logger.Logger) (conn ne
|
|||||||
}
|
}
|
||||||
cc, err = preNode.Options().Transport.Connect(ctx, cn, "tcp", addr)
|
cc, err = preNode.Options().Transport.Connect(ctx, cn, "tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if cc != nil {
|
||||||
|
cc.Close()
|
||||||
|
}
|
||||||
cn.Close()
|
cn.Close()
|
||||||
if marker != nil {
|
if marker != nil {
|
||||||
marker.Mark()
|
marker.Mark()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cc, err = node.Options().Transport.Handshake(ctx, cc)
|
var cc2 net.Conn
|
||||||
|
cc2, err = node.Options().Transport.Handshake(ctx, cc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if cc2 != nil {
|
||||||
|
cc2.Close()
|
||||||
|
}
|
||||||
|
cc.Close()
|
||||||
cn.Close()
|
cn.Close()
|
||||||
if marker != nil {
|
if marker != nil {
|
||||||
marker.Mark()
|
marker.Mark()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
cc = cc2
|
||||||
if marker != nil {
|
if marker != nil {
|
||||||
marker.Reset()
|
marker.Reset()
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-3
@@ -90,6 +90,7 @@ func (r *Router) dial(ctx context.Context, network, address string, log logger.L
|
|||||||
log.Debugf("dial %s/%s", address, network)
|
log.Debugf("dial %s/%s", address, network)
|
||||||
|
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
|
func() {
|
||||||
ctx := ctx
|
ctx := ctx
|
||||||
if r.options.Timeout > 0 {
|
if r.options.Timeout > 0 {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
@@ -106,7 +107,7 @@ func (r *Router) dial(ctx context.Context, network, address string, log logger.L
|
|||||||
ipAddr, err = xnet.Resolve(ctx, "ip", address, r.options.Resolver, r.options.HostMapper, log)
|
ipAddr, err = xnet.Resolve(ctx, "ip", address, r.options.Resolver, r.options.HostMapper, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if buf != nil {
|
if buf != nil {
|
||||||
@@ -139,9 +140,13 @@ func (r *Router) dial(ctx context.Context, network, address string, log logger.L
|
|||||||
}, callerOpts...)...,
|
}, callerOpts...)...,
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
log.Errorf("route(retry=%d) %s", i, err)
|
log.Errorf("route(retry=%d) %s", i, err)
|
||||||
|
}()
|
||||||
|
if conn != nil || err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -160,6 +165,7 @@ func (r *Router) Bind(ctx context.Context, network, address string, opts ...chai
|
|||||||
log.Debugf("bind on %s/%s", address, network)
|
log.Debugf("bind on %s/%s", address, network)
|
||||||
|
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
|
func() {
|
||||||
ctx := ctx
|
ctx := ctx
|
||||||
if r.options.Timeout > 0 {
|
if r.options.Timeout > 0 {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
@@ -190,9 +196,13 @@ func (r *Router) Bind(ctx context.Context, network, address string, opts ...chai
|
|||||||
}
|
}
|
||||||
ln, err = route.Bind(ctx, network, address, opts...)
|
ln, err = route.Bind(ctx, network, address, opts...)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
log.Errorf("route(retry=%d) %s", i, err)
|
log.Errorf("route(retry=%d) %s", i, err)
|
||||||
|
}()
|
||||||
|
if ln != nil || err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
+1
-1
@@ -102,5 +102,5 @@ func (tr *Transport) Options() *chain.TransportOptions {
|
|||||||
func (tr *Transport) Copy() chain.Transporter {
|
func (tr *Transport) Copy() chain.Transporter {
|
||||||
tr2 := &Transport{}
|
tr2 := &Transport{}
|
||||||
*tr2 = *tr
|
*tr2 = *tr
|
||||||
return tr
|
return tr2
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user