From 05abb7025e6ad47eeb589e5ed47301a6be89c9d9 Mon Sep 17 00:00:00 2001 From: yfsn666 Date: Wed, 19 Aug 2026 22:11:52 +0800 Subject: [PATCH] [INLONG-12202][SDK] Close connPool before netClient to avoid dial goroutine leak in Dataproxy Go SDK --- .../dataproxy-sdk-golang/dataproxy/client.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/dataproxy/client.go b/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/dataproxy/client.go index f06b249a6b..44e0a901d8 100755 --- a/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/dataproxy/client.go +++ b/inlong-sdk/dataproxy-sdk-twins/dataproxy-sdk-golang/dataproxy/client.go @@ -279,12 +279,22 @@ func (c *client) Close() { for _, w := range c.workers { w.close() } - if c.netClient != nil { - _ = c.netClient.Stop() - } + // The connection pool must be closed before netClient. Once netClient.Stop() + // returns, gnet's event-loop has fully exited. After that, calling Dial will + // block forever inside gnet.Client.EnrollContext, waiting on the channel that + // signals connection registration completion (no event-loop is left to + // execute the registration task), causing a goroutine leak. The pool's + // Close() waits for in-flight dials to finish within a bounded time, trying + // to avoid new dials entering EnrollContext after netClient has stopped; + // for external Dialers that block indefinitely, Close will still return + // after the timeout. if c.connPool != nil { c.connPool.Close() } + // Close netClient + if c.netClient != nil { + _ = c.netClient.Stop() + } }) }