From a5db80d710814a5d0209cfd7d9b9b40f24975b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Wed, 31 Dec 2025 02:18:51 +0800 Subject: [PATCH] Fix nfqueue fallback when kernel module unavailable --- nfqueue_linux.go | 30 ++++++++++++------------------ redirect_linux.go | 4 ++-- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/nfqueue_linux.go b/nfqueue_linux.go index 10f253f..e52cd46 100644 --- a/nfqueue_linux.go +++ b/nfqueue_linux.go @@ -5,7 +5,6 @@ package tun import ( "context" "errors" - "sync" "sync/atomic" "github.com/sagernet/sing-tun/internal/gtcpip/header" @@ -30,7 +29,6 @@ type nfqueueHandler struct { queue uint16 outputMark uint32 resetMark uint32 - wg sync.WaitGroup closed atomic.Bool } @@ -82,28 +80,25 @@ func (h *nfqueueHandler) Start() error { if err != nil { return E.Cause(err, "open nfqueue") } - h.nfq = nfq if err = nfq.SetOption(netlink.NoENOBUFS, true); err != nil { - h.nfq.Close() + nfq.Close() return E.Cause(err, "set nfqueue option") } - h.wg.Add(1) - go func() { - defer h.wg.Done() - err := nfq.RegisterWithErrorFunc(h.ctx, h.handlePacket, func(e error) int { - if h.ctx.Err() != nil { - return 1 - } - h.logger.Error("nfqueue error: ", e) - return 0 - }) - if err != nil && h.ctx.Err() == nil { - h.logger.Error("nfqueue register error: ", err) + err = nfq.RegisterWithErrorFunc(h.ctx, h.handlePacket, func(e error) int { + if h.ctx.Err() != nil { + return 1 } - }() + h.logger.Error("nfqueue error: ", e) + return 0 + }) + if err != nil { + nfq.Close() + return E.Cause(err, "register nfqueue") + } + h.nfq = nfq return nil } @@ -239,6 +234,5 @@ func (h *nfqueueHandler) Close() error { if h.nfq != nil { h.nfq.Close() } - h.wg.Wait() return nil } diff --git a/redirect_linux.go b/redirect_linux.go index 2a638ee..5bea0c4 100644 --- a/redirect_linux.go +++ b/redirect_linux.go @@ -143,9 +143,9 @@ func (r *autoRedirect) Start() error { ResetMark: r.effectiveResetMark(), }) if err != nil { - r.logger.Warn("nfqueue not available, pre-match disabled: ", err) + r.logger.Warn("nfqueue not available, pre-match disabled (missing nfnetlink_queue and nft_queue kernel module?): ", err) } else if err = handler.Start(); err != nil { - r.logger.Warn("nfqueue start failed, pre-match disabled: ", err) + r.logger.Warn("nfqueue start failed, pre-match disabled (missing nfnetlink_queue and nft_queue kernel module?): ", err) } else { r.nfqueueHandler = handler r.nfqueueEnabled = true