Compare commits

...

3 Commits

Author SHA1 Message Date
ginuerzh 286c1615fd build(deps): bump go-gost/x from v0.12.0 to v0.12.1 2026-06-21 22:55:44 +08:00
ginuerzh b985e5138c fix: use atomic int for multi-worker exit code and clean up cancellation
- Replace bare int with atomic.Int32 to fix data race on ret
- Replace wg.Add/go/defer wg.Done pattern with wg.Go (Go 1.22+)
- Pass context by value instead of pointer
- Add ctx.Err() guard to suppress fatal on cancellation errors
- Add ProcessState nil check before accessing ExitCode
- Move cancel() after wg.Wait() to avoid race where a successful
  worker's deferred cancel kills siblings and triggers log.Fatal
2026-06-21 21:07:37 +08:00
ginuerzh b628475871 fix: enable metrics before loading services
Move xmetrics.Enable(true) from run() to Start(), before loader.Load(),
so that listener wrappers can observe the enabled state at Init time
rather than after wrapper decisions have already been made.
2026-06-21 20:35:19 +08:00
4 changed files with 44 additions and 27 deletions

View File

@ -11,6 +11,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/go-gost/core/logger" "github.com/go-gost/core/logger"
@ -48,39 +49,43 @@ func init() {
if strings.Contains(args, " -- ") { if strings.Contains(args, " -- ") {
var ( var (
wg sync.WaitGroup wg sync.WaitGroup
ret int ret atomic.Int32
) )
ctx, cancel := context.WithCancel(context.Background()) wargsList := strings.Split(" "+args+" ", " -- ")
defer cancel()
for wid, wargs := range strings.Split(" "+args+" ", " -- ") { ctx, cancel := context.WithCancel(context.Background())
wg.Add(1)
go func(wid int, wargs string) { for wid, wargs := range wargsList {
defer wg.Done() wg.Go(func() {
defer cancel() worker(wid, strings.Split(strings.TrimSpace(wargs), " "), ctx, &ret)
worker(wid, strings.Split(wargs, " "), &ctx, &ret) })
}(wid, strings.TrimSpace(wargs))
} }
wg.Wait() wg.Wait()
cancel()
os.Exit(ret) os.Exit(int(ret.Load()))
} }
} }
func worker(id int, args []string, ctx *context.Context, ret *int) { func worker(id int, args []string, ctx context.Context, ret *atomic.Int32) {
cmd := exec.CommandContext(*ctx, os.Args[0], args...) cmd := exec.CommandContext(ctx, os.Args[0], args...)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
cmd.Env = append(os.Environ(), fmt.Sprintf("_GOST_ID=%d", id)) cmd.Env = append(os.Environ(), fmt.Sprintf("_GOST_ID=%d", id))
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
// Context cancellation is expected when one worker exits early.
// Only log fatal on other errors.
if ctx.Err() == nil {
log.Fatal(err) log.Fatal(err)
} }
if cmd.ProcessState.Exited() { return
*ret = cmd.ProcessState.ExitCode() }
if cmd.ProcessState != nil && cmd.ProcessState.Exited() {
ret.Store(int32(cmd.ProcessState.ExitCode()))
} }
} }

View File

@ -62,6 +62,12 @@ func (p *program) Start() error {
config.Set(cfg) config.Set(cfg)
// Enable metrics before loading services so that listener wrappers
// can observe the enabled state at Init time.
if cfg.Metrics != nil && cfg.Metrics.Addr != "" {
xmetrics.Enable(true)
}
if err := loader.Load(cfg); err != nil { if err := loader.Load(cfg); err != nil {
return err return err
} }
@ -121,8 +127,6 @@ func (p *program) run(cfg *config.Config) error {
p.srvMetrics = s p.srvMetrics = s
xmetrics.Enable(true)
go func() { go func() {
defer s.Close() defer s.Close()

8
go.mod
View File

@ -3,8 +3,8 @@ module github.com/go-gost/gost
go 1.26.3 go 1.26.3
require ( require (
github.com/go-gost/core v0.4.1 github.com/go-gost/core v0.4.2
github.com/go-gost/x v0.12.0 github.com/go-gost/x v0.12.1
github.com/judwhite/go-svc v1.2.1 github.com/judwhite/go-svc v1.2.1
github.com/moby/moby/client v0.4.0 github.com/moby/moby/client v0.4.0
github.com/stretchr/testify v1.11.1 github.com/stretchr/testify v1.11.1
@ -50,7 +50,7 @@ require (
github.com/go-gost/gosocks4 v0.1.0 // indirect github.com/go-gost/gosocks4 v0.1.0 // indirect
github.com/go-gost/gosocks5 v0.5.0 // indirect github.com/go-gost/gosocks5 v0.5.0 // indirect
github.com/go-gost/plugin v0.3.0 // indirect github.com/go-gost/plugin v0.3.0 // indirect
github.com/go-gost/relay v0.6.0 // indirect github.com/go-gost/relay v0.6.1 // indirect
github.com/go-gost/tls-dissector v0.2.0 // indirect github.com/go-gost/tls-dissector v0.2.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
@ -116,7 +116,9 @@ require (
github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740 // indirect github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740 // indirect
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
github.com/shirou/gopsutil/v4 v4.26.3 // indirect github.com/shirou/gopsutil/v4 v4.26.3 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect github.com/sirupsen/logrus v1.9.4 // indirect
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 // indirect github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect

18
go.sum
View File

@ -83,8 +83,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-gost/core v0.4.1 h1:/MZYv0tSkw9yoK2nl0GLl3GjT1/3qKl5u3E/DADyeZE= github.com/go-gost/core v0.4.2 h1:NBCkdWItIiwt15cA2mkRza/u6ukxQVSW74bc33o70zE=
github.com/go-gost/core v0.4.1/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A= github.com/go-gost/core v0.4.2/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A=
github.com/go-gost/go-shadowsocks2 v0.1.3 h1:6CUZLp+mTWXnKP2aK8/Z9ZP+ERMX9gSbywmPu4kGX/A= github.com/go-gost/go-shadowsocks2 v0.1.3 h1:6CUZLp+mTWXnKP2aK8/Z9ZP+ERMX9gSbywmPu4kGX/A=
github.com/go-gost/go-shadowsocks2 v0.1.3/go.mod h1:866zFNNI3He6Wef1M/IvAjTal74WhcfKfBgRpTlkKys= github.com/go-gost/go-shadowsocks2 v0.1.3/go.mod h1:866zFNNI3He6Wef1M/IvAjTal74WhcfKfBgRpTlkKys=
github.com/go-gost/gosocks4 v0.1.0 h1:eAzev6qw4fzkFQKC9uCHLVNnnPdHyqCggbnfNN80Pmk= github.com/go-gost/gosocks4 v0.1.0 h1:eAzev6qw4fzkFQKC9uCHLVNnnPdHyqCggbnfNN80Pmk=
@ -93,12 +93,12 @@ github.com/go-gost/gosocks5 v0.5.0 h1:YE37l1MJwde8diIQdynStqogMotG5enoTdborhA5yi
github.com/go-gost/gosocks5 v0.5.0/go.mod h1:1G6I7HP7VFVxveGkoK8mnprnJqSqJjdcASKsdUn4Pp4= github.com/go-gost/gosocks5 v0.5.0/go.mod h1:1G6I7HP7VFVxveGkoK8mnprnJqSqJjdcASKsdUn4Pp4=
github.com/go-gost/plugin v0.3.0 h1:pmll8nNd9PX92BWMB5+b2y2SEkBAWJLxD2ANfX+WHuw= github.com/go-gost/plugin v0.3.0 h1:pmll8nNd9PX92BWMB5+b2y2SEkBAWJLxD2ANfX+WHuw=
github.com/go-gost/plugin v0.3.0/go.mod h1:oN23l+yGDCIP9G3KnDl/I/0zVGOobZUDCB2Z5yYYXts= github.com/go-gost/plugin v0.3.0/go.mod h1:oN23l+yGDCIP9G3KnDl/I/0zVGOobZUDCB2Z5yYYXts=
github.com/go-gost/relay v0.6.0 h1:o8r0B3eTw8Rwwent+5x5Cw1g4AyNUl4hNqiyDJXkFvA= github.com/go-gost/relay v0.6.1 h1:7SqnHFbY8x/DzvjpK03a5zcVH9+TbJAcnW/RT6s1ecc=
github.com/go-gost/relay v0.6.0/go.mod h1:Dku0f5sfjOClrZFiDmQUrYYJ4uof7rnkCUBfsl0PSAI= github.com/go-gost/relay v0.6.1/go.mod h1:Dku0f5sfjOClrZFiDmQUrYYJ4uof7rnkCUBfsl0PSAI=
github.com/go-gost/tls-dissector v0.2.0 h1:9tE6WOzzpurATTBWn60DU4R8gibpGNY8/qVcc1SicVg= github.com/go-gost/tls-dissector v0.2.0 h1:9tE6WOzzpurATTBWn60DU4R8gibpGNY8/qVcc1SicVg=
github.com/go-gost/tls-dissector v0.2.0/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs= github.com/go-gost/tls-dissector v0.2.0/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs=
github.com/go-gost/x v0.12.0 h1:gHiLZ4b6wLEsACzAsS6TDWgJnSFeIv822EBdMrpWtag= github.com/go-gost/x v0.12.1 h1:gemrGRucwroz7xkhjgTfkG0F8YDC1uKSlT6McGhCbhU=
github.com/go-gost/x v0.12.0/go.mod h1:mUbt9jmZDDxq1ERbtcMVFndzFHgICjMDWiaManx/tRU= github.com/go-gost/x v0.12.1/go.mod h1:hrewVDMVncuoRwteqJr/ReMN/a/IunlVN/zCZajr9Q8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@ -272,8 +272,14 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740 h1:XdDrN8rtxdgW3TLn7pAuobI9PhPMbf6Geu9nvFzXn2E= github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740 h1:XdDrN8rtxdgW3TLn7pAuobI9PhPMbf6Geu9nvFzXn2E=
github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740/go.mod h1:Oqfn/ykzqjeX00+7IuPyR7wGYgOzld0Tni6djgElacI= github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740/go.mod h1:Oqfn/ykzqjeX00+7IuPyR7wGYgOzld0Tni6djgElacI=
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc= github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc=
github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=