Skip to content

Commit 26d1d6e

Browse files
committed
Fix server goroutine leak in forwardRequest: add handshake deadline
forwardRequest opens a stream to the destination and reads the response. If the destination accepts but never responds, readObject blocks forever — observed as 2.4K+ stuck goroutines per server, growing rapidly after restart. The idle timeout fix (PR skycoin#372) only covered the bridge phase (CopyReadWriteCloser). This adds HandshakeTimeout to the forwardRequest handshake read, matching the client-side behavior.
1 parent e26b298 commit 26d1d6e

1 file changed

Lines changed: 10 additions & 0 deletions

File tree

pkg/dmsg/server_session.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,12 +366,22 @@ func (ss *ServerSession) forwardRequest(req StreamRequest) (mStr io.ReadWriteClo
366366
return nil, nil, err
367367
}
368368
}
369+
// Set a deadline for the forwarding handshake. If the destination visor
370+
// accepts the stream but never responds, readObject blocks forever,
371+
// leaking goroutines. Observed as 2K+ stuck goroutines per DMSG server.
372+
if conn, ok := mStr.(net.Conn); ok {
373+
conn.SetDeadline(time.Now().Add(HandshakeTimeout)) //nolint:errcheck,gosec
374+
}
369375
if err = ss.writeObject(mStr, req.raw); err != nil {
370376
return nil, nil, err
371377
}
372378
if respObj, err = ss.readObject(mStr); err != nil {
373379
return nil, nil, err
374380
}
381+
// Clear deadline before returning the stream for long-lived bridging.
382+
if conn, ok := mStr.(net.Conn); ok {
383+
conn.SetDeadline(time.Time{}) //nolint:errcheck,gosec
384+
}
375385
var resp StreamResponse
376386
if resp, err = respObj.ObtainStreamResponse(); err != nil {
377387
return nil, nil, err

0 commit comments

Comments
 (0)