Skip to content

Commit 44c9704

Browse files
committed
Wait for all streams to close before destroying engine
Prevents race condition where engine destroy could delete stream adapters while Go code is still reading/writing.
1 parent b19702b commit 44c9704

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

naive_client.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/json"
77
"net"
88
"net/url"
9+
"sync"
910
"sync/atomic"
1011

1112
"github.com/sagernet/sing/common/bufio"
@@ -45,6 +46,7 @@ type NaiveClient struct {
4546
engine Engine
4647
streamEngine StreamEngine
4748
tcpForwarder net.Listener
49+
activeConnections sync.WaitGroup
4850
}
4951

5052
func NewNaiveClient(config NaiveClientConfig) (*NaiveClient, error) {
@@ -165,17 +167,23 @@ func (c *NaiveClient) DialContext(ctx context.Context, destination M.Socksaddr)
165167
concurrencyIndex := int(c.counter.Add(1) % uint64(c.concurrency))
166168
headers["-network-isolation-key"] = F.ToString("https://pool-", concurrencyIndex, ":443")
167169
}
170+
c.activeConnections.Add(1)
168171
conn := c.streamEngine.CreateConn(true, false)
169172
err := conn.Start("CONNECT", c.serverURL, headers, 0, false)
170173
if err != nil {
174+
c.activeConnections.Done()
171175
return nil, err
172176
}
173177

174-
return NewNaiveConn(conn), nil
178+
return &trackedNaiveConn{
179+
NaiveConn: NewNaiveConn(conn),
180+
onClose: c.activeConnections.Done,
181+
}, nil
175182
}
176183

177184
func (c *NaiveClient) Close() error {
178185
c.tcpForwarder.Close()
186+
c.activeConnections.Wait()
179187
c.engine.Shutdown()
180188
c.engine.Destroy()
181189
return nil
@@ -199,3 +207,14 @@ func (c *NaiveClient) forwardConnection(conn net.Conn) {
199207
}
200208
bufio.CopyConn(c.ctx, conn, serverConn)
201209
}
210+
211+
type trackedNaiveConn struct {
212+
*NaiveConn
213+
onClose func()
214+
closeOnce sync.Once
215+
}
216+
217+
func (c *trackedNaiveConn) Close() error {
218+
c.closeOnce.Do(c.onClose)
219+
return c.NaiveConn.Close()
220+
}

0 commit comments

Comments
 (0)