From 03981232610db7c87c72adef2fde7989bebefc7c Mon Sep 17 00:00:00 2001 From: Fangliding Date: Wed, 14 Jan 2026 20:54:32 +0800 Subject: [PATCH] Fix ss2022 udp leak --- common/singbridge/packet.go | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/common/singbridge/packet.go b/common/singbridge/packet.go index fef955e76a1c..d4dccb4ce538 100644 --- a/common/singbridge/packet.go +++ b/common/singbridge/packet.go @@ -2,10 +2,12 @@ package singbridge import ( "context" + "time" B "github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/bufio" M "github.com/sagernet/sing/common/metadata" + "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/transport" @@ -29,6 +31,8 @@ type PacketConnWrapper struct { cached buf.MultiBuffer } +// This ReadPacket implemented a timeout to avoid goroutine leak like PipeConnWrapper.Read() +// as a temporarily solution func (w *PacketConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) { if w.cached != nil { mb, bb := buf.SplitFirst(w.cached) @@ -47,10 +51,30 @@ func (w *PacketConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) { return ToSocksaddr(destination), nil } } - mb, err := w.ReadMultiBuffer() - if err != nil { - return M.Socksaddr{}, err + + // timeout + type readResult struct { + mb buf.MultiBuffer + err error + } + c := make(chan readResult, 1) + go func() { + mb, err := w.ReadMultiBuffer() + c <- readResult{mb: mb, err: err} + }() + var mb buf.MultiBuffer + select { + case <-time.After(60 * time.Second): + common.Close(w.Reader) + common.Interrupt(w.Reader) + return M.Socksaddr{}, buf.ErrReadTimeout + case result := <-c: + if result.err != nil { + return M.Socksaddr{}, result.err + } + mb = result.mb } + nb, bb := buf.SplitFirst(mb) if bb == nil { return M.Socksaddr{}, nil