From 8c1d6c3918745fefd333ff2fabee7109f5a98757 Mon Sep 17 00:00:00 2001 From: sunshineplan Date: Mon, 1 Jul 2024 13:19:50 +0800 Subject: [PATCH 1/4] Add pprof flag for debugging --- main/commands/run.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/main/commands/run.go b/main/commands/run.go index 066bfae1845..328aff01018 100644 --- a/main/commands/run.go +++ b/main/commands/run.go @@ -3,6 +3,8 @@ package commands import ( "fmt" "log" + "net/http" + _ "net/http/pprof" "os" "os/signal" "path/filepath" @@ -61,11 +63,14 @@ var ( configDirs cmdarg.Arg configFormat *string configDirRecursively *bool + + configPprof *string ) func setConfigFlags(cmd *base.Command) { configFormat = cmd.Flag.String("format", core.FormatAuto, "") configDirRecursively = cmd.Flag.Bool("r", false, "") + configPprof = cmd.Flag.String("pprof", "", "") cmd.Flag.Var(&configFiles, "config", "") cmd.Flag.Var(&configFiles, "c", "") @@ -83,6 +88,14 @@ func executeRun(cmd *base.Command, args []string) { base.Fatalf("Failed to start: %s", err) } + if addr := *configPprof; addr != "" { + go func() { + if err := http.ListenAndServe(addr, nil); err != nil { + log.Print(err) + } + }() + } + if err := server.Start(); err != nil { base.Fatalf("Failed to start: %s", err) } From 72312e4ab72fbc71e80e9ec6e778ffbc4d84b50f Mon Sep 17 00:00:00 2001 From: sunshineplan Date: Tue, 20 Aug 2024 10:41:09 +0800 Subject: [PATCH 2/4] Use pprof build tag for pprof debugging --- main/commands/run.go | 81 ------------------------------- main/commands/run_default.go | 78 ++++++++++++++++++++++++++++++ main/commands/run_pprof.go | 93 ++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 81 deletions(-) create mode 100644 main/commands/run_default.go create mode 100644 main/commands/run_pprof.go diff --git a/main/commands/run.go b/main/commands/run.go index 328aff01018..b948b9f7433 100644 --- a/main/commands/run.go +++ b/main/commands/run.go @@ -3,14 +3,9 @@ package commands import ( "fmt" "log" - "net/http" - _ "net/http/pprof" "os" - "os/signal" "path/filepath" - "runtime" "strings" - "syscall" core "github.com/v2fly/v2ray-core/v5" "github.com/v2fly/v2ray-core/v5/common/cmdarg" @@ -18,59 +13,16 @@ import ( "github.com/v2fly/v2ray-core/v5/main/commands/base" ) -// CmdRun runs V2Ray with config -var CmdRun = &base.Command{ - CustomFlags: true, - UsageLine: "{{.Exec}} run [-c config.json] [-d dir]", - Short: "run V2Ray with config", - Long: ` -Run V2Ray with config. - -{{.Exec}} will also use the config directory specified by environment -variable "v2ray.location.confdir". If no config found, it tries -to load config from one of below: - - 1. The default "config.json" in the current directory - 2. The config file from ENV "v2ray.location.config" - 3. The stdin if all failed above - -Arguments: - - -c, -config - Config file for V2Ray. Multiple assign is accepted. - - -d, -confdir - A directory with config files. Multiple assign is accepted. - - -r - Load confdir recursively. - - -format - Format of config input. (default "auto") - -Examples: - - {{.Exec}} {{.LongName}} -c config.json - {{.Exec}} {{.LongName}} -d path/to/dir - -Use "{{.Exec}} help format-loader" for more information about format. - `, - Run: executeRun, -} - var ( configFiles cmdarg.Arg configDirs cmdarg.Arg configFormat *string configDirRecursively *bool - - configPprof *string ) func setConfigFlags(cmd *base.Command) { configFormat = cmd.Flag.String("format", core.FormatAuto, "") configDirRecursively = cmd.Flag.Bool("r", false, "") - configPprof = cmd.Flag.String("pprof", "", "") cmd.Flag.Var(&configFiles, "config", "") cmd.Flag.Var(&configFiles, "c", "") @@ -78,39 +30,6 @@ func setConfigFlags(cmd *base.Command) { cmd.Flag.Var(&configDirs, "d", "") } -func executeRun(cmd *base.Command, args []string) { - setConfigFlags(cmd) - cmd.Flag.Parse(args) - printVersion() - configFiles = getConfigFilePath() - server, err := startV2Ray() - if err != nil { - base.Fatalf("Failed to start: %s", err) - } - - if addr := *configPprof; addr != "" { - go func() { - if err := http.ListenAndServe(addr, nil); err != nil { - log.Print(err) - } - }() - } - - if err := server.Start(); err != nil { - base.Fatalf("Failed to start: %s", err) - } - defer server.Close() - - // Explicitly triggering GC to remove garbage from config loading. - runtime.GC() - - { - osSignals := make(chan os.Signal, 1) - signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM) - <-osSignals - } -} - func fileExists(file string) bool { info, err := os.Stat(file) return err == nil && !info.IsDir() diff --git a/main/commands/run_default.go b/main/commands/run_default.go new file mode 100644 index 00000000000..3a44b23c8e8 --- /dev/null +++ b/main/commands/run_default.go @@ -0,0 +1,78 @@ +//go:build !pprof +// +build !pprof + +package commands + +import ( + "os" + "os/signal" + "runtime" + "syscall" + + "github.com/v2fly/v2ray-core/v5/main/commands/base" +) + +// CmdRun runs V2Ray with config +var CmdRun = &base.Command{ + CustomFlags: true, + UsageLine: "{{.Exec}} run [-c config.json] [-d dir]", + Short: "run V2Ray with config", + Long: ` +Run V2Ray with config. + +{{.Exec}} will also use the config directory specified by environment +variable "v2ray.location.confdir". If no config found, it tries +to load config from one of below: + + 1. The default "config.json" in the current directory + 2. The config file from ENV "v2ray.location.config" + 3. The stdin if all failed above + +Arguments: + + -c, -config + Config file for V2Ray. Multiple assign is accepted. + + -d, -confdir + A directory with config files. Multiple assign is accepted. + + -r + Load confdir recursively. + + -format + Format of config input. (default "auto") + +Examples: + + {{.Exec}} {{.LongName}} -c config.json + {{.Exec}} {{.LongName}} -d path/to/dir + +Use "{{.Exec}} help format-loader" for more information about format. + `, + Run: executeRun, +} + +func executeRun(cmd *base.Command, args []string) { + setConfigFlags(cmd) + cmd.Flag.Parse(args) + printVersion() + configFiles = getConfigFilePath() + server, err := startV2Ray() + if err != nil { + base.Fatalf("Failed to start: %s", err) + } + + if err := server.Start(); err != nil { + base.Fatalf("Failed to start: %s", err) + } + defer server.Close() + + // Explicitly triggering GC to remove garbage from config loading. + runtime.GC() + + { + osSignals := make(chan os.Signal, 1) + signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM) + <-osSignals + } +} diff --git a/main/commands/run_pprof.go b/main/commands/run_pprof.go new file mode 100644 index 00000000000..201a459a26a --- /dev/null +++ b/main/commands/run_pprof.go @@ -0,0 +1,93 @@ +//go:build pprof +// +build pprof + +package commands + +import ( + "log" + "net/http" + _ "net/http/pprof" + "os" + "os/signal" + "runtime" + "syscall" + + "github.com/v2fly/v2ray-core/v5/main/commands/base" +) + +// CmdRun runs V2Ray with config +var CmdRun = &base.Command{ + CustomFlags: true, + UsageLine: "{{.Exec}} run [-c config.json] [-d dir] [-pprof port]", + Short: "run V2Ray with config", + Long: ` +Run V2Ray with config. + +{{.Exec}} will also use the config directory specified by environment +variable "v2ray.location.confdir". If no config found, it tries +to load config from one of below: + + 1. The default "config.json" in the current directory + 2. The config file from ENV "v2ray.location.config" + 3. The stdin if all failed above + +Arguments: + + -c, -config + Config file for V2Ray. Multiple assign is accepted. + + -d, -confdir + A directory with config files. Multiple assign is accepted. + + -r + Load confdir recursively. + + -format + Format of config input. (default "auto") + + -pprof + HTTP server port for pprof debugging. (default "8080") + +Examples: + + {{.Exec}} {{.LongName}} -c config.json + {{.Exec}} {{.LongName}} -d path/to/dir + +Use "{{.Exec}} help format-loader" for more information about format. + `, + Run: executeRun, +} + +func executeRun(cmd *base.Command, args []string) { + setConfigFlags(cmd) + pprof := cmd.Flag.String("pprof", ":8080", "") + cmd.Flag.Parse(args) + printVersion() + configFiles = getConfigFilePath() + server, err := startV2Ray() + if err != nil { + base.Fatalf("Failed to start: %s", err) + } + + if addr := *pprof; addr != "" { + go func() { + if err := http.ListenAndServe(addr, nil); err != nil { + log.Print(err) + } + }() + } + + if err := server.Start(); err != nil { + base.Fatalf("Failed to start: %s", err) + } + defer server.Close() + + // Explicitly triggering GC to remove garbage from config loading. + runtime.GC() + + { + osSignals := make(chan os.Signal, 1) + signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM) + <-osSignals + } +} From effa2fcc56d833d76240a268be636c2041565f17 Mon Sep 17 00:00:00 2001 From: sunshineplan Date: Thu, 22 Aug 2024 10:50:05 +0800 Subject: [PATCH 3/4] Register pprof as a plugin --- main/commands/run.go | 83 ++++++++++++++++++++++++++++++++ main/commands/run_default.go | 78 ------------------------------ main/commands/run_pprof.go | 93 ------------------------------------ main/plugins/plugin.go | 11 +++++ main/plugins/plugin_pprof.go | 28 +++++++++++ 5 files changed, 122 insertions(+), 171 deletions(-) delete mode 100644 main/commands/run_default.go delete mode 100644 main/commands/run_pprof.go create mode 100644 main/plugins/plugin.go create mode 100644 main/plugins/plugin_pprof.go diff --git a/main/commands/run.go b/main/commands/run.go index b948b9f7433..2fbb7a2bce0 100644 --- a/main/commands/run.go +++ b/main/commands/run.go @@ -4,15 +4,59 @@ import ( "fmt" "log" "os" + "os/signal" "path/filepath" + "runtime" "strings" + "syscall" core "github.com/v2fly/v2ray-core/v5" "github.com/v2fly/v2ray-core/v5/common/cmdarg" "github.com/v2fly/v2ray-core/v5/common/platform" "github.com/v2fly/v2ray-core/v5/main/commands/base" + "github.com/v2fly/v2ray-core/v5/main/plugins" ) +// CmdRun runs V2Ray with config +var CmdRun = &base.Command{ + CustomFlags: true, + UsageLine: "{{.Exec}} run [-c config.json] [-d dir]", + Short: "run V2Ray with config", + Long: ` +Run V2Ray with config. + +{{.Exec}} will also use the config directory specified by environment +variable "v2ray.location.confdir". If no config found, it tries +to load config from one of below: + + 1. The default "config.json" in the current directory + 2. The config file from ENV "v2ray.location.config" + 3. The stdin if all failed above + +Arguments: + + -c, -config + Config file for V2Ray. Multiple assign is accepted. + + -d, -confdir + A directory with config files. Multiple assign is accepted. + + -r + Load confdir recursively. + + -format + Format of config input. (default "auto") + +Examples: + + {{.Exec}} {{.LongName}} -c config.json + {{.Exec}} {{.LongName}} -d path/to/dir + +Use "{{.Exec}} help format-loader" for more information about format. + `, + Run: executeRun, +} + var ( configFiles cmdarg.Arg configDirs cmdarg.Arg @@ -30,6 +74,45 @@ func setConfigFlags(cmd *base.Command) { cmd.Flag.Var(&configDirs, "d", "") } +func executeRun(cmd *base.Command, args []string) { + setConfigFlags(cmd) + var pluginFuncs []func() error + for _, plugin := range plugins.Plugins { + if f := plugin(cmd); f != nil { + pluginFuncs = append(pluginFuncs, f) + } + } + cmd.Flag.Parse(args) + printVersion() + configFiles = getConfigFilePath() + server, err := startV2Ray() + if err != nil { + base.Fatalf("Failed to start: %s", err) + } + + for _, f := range pluginFuncs { + go func(f func() error) { + if err := f(); err != nil { + log.Print(err) + } + }(f) + } + + if err := server.Start(); err != nil { + base.Fatalf("Failed to start: %s", err) + } + defer server.Close() + + // Explicitly triggering GC to remove garbage from config loading. + runtime.GC() + + { + osSignals := make(chan os.Signal, 1) + signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM) + <-osSignals + } +} + func fileExists(file string) bool { info, err := os.Stat(file) return err == nil && !info.IsDir() diff --git a/main/commands/run_default.go b/main/commands/run_default.go deleted file mode 100644 index 3a44b23c8e8..00000000000 --- a/main/commands/run_default.go +++ /dev/null @@ -1,78 +0,0 @@ -//go:build !pprof -// +build !pprof - -package commands - -import ( - "os" - "os/signal" - "runtime" - "syscall" - - "github.com/v2fly/v2ray-core/v5/main/commands/base" -) - -// CmdRun runs V2Ray with config -var CmdRun = &base.Command{ - CustomFlags: true, - UsageLine: "{{.Exec}} run [-c config.json] [-d dir]", - Short: "run V2Ray with config", - Long: ` -Run V2Ray with config. - -{{.Exec}} will also use the config directory specified by environment -variable "v2ray.location.confdir". If no config found, it tries -to load config from one of below: - - 1. The default "config.json" in the current directory - 2. The config file from ENV "v2ray.location.config" - 3. The stdin if all failed above - -Arguments: - - -c, -config - Config file for V2Ray. Multiple assign is accepted. - - -d, -confdir - A directory with config files. Multiple assign is accepted. - - -r - Load confdir recursively. - - -format - Format of config input. (default "auto") - -Examples: - - {{.Exec}} {{.LongName}} -c config.json - {{.Exec}} {{.LongName}} -d path/to/dir - -Use "{{.Exec}} help format-loader" for more information about format. - `, - Run: executeRun, -} - -func executeRun(cmd *base.Command, args []string) { - setConfigFlags(cmd) - cmd.Flag.Parse(args) - printVersion() - configFiles = getConfigFilePath() - server, err := startV2Ray() - if err != nil { - base.Fatalf("Failed to start: %s", err) - } - - if err := server.Start(); err != nil { - base.Fatalf("Failed to start: %s", err) - } - defer server.Close() - - // Explicitly triggering GC to remove garbage from config loading. - runtime.GC() - - { - osSignals := make(chan os.Signal, 1) - signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM) - <-osSignals - } -} diff --git a/main/commands/run_pprof.go b/main/commands/run_pprof.go deleted file mode 100644 index 201a459a26a..00000000000 --- a/main/commands/run_pprof.go +++ /dev/null @@ -1,93 +0,0 @@ -//go:build pprof -// +build pprof - -package commands - -import ( - "log" - "net/http" - _ "net/http/pprof" - "os" - "os/signal" - "runtime" - "syscall" - - "github.com/v2fly/v2ray-core/v5/main/commands/base" -) - -// CmdRun runs V2Ray with config -var CmdRun = &base.Command{ - CustomFlags: true, - UsageLine: "{{.Exec}} run [-c config.json] [-d dir] [-pprof port]", - Short: "run V2Ray with config", - Long: ` -Run V2Ray with config. - -{{.Exec}} will also use the config directory specified by environment -variable "v2ray.location.confdir". If no config found, it tries -to load config from one of below: - - 1. The default "config.json" in the current directory - 2. The config file from ENV "v2ray.location.config" - 3. The stdin if all failed above - -Arguments: - - -c, -config - Config file for V2Ray. Multiple assign is accepted. - - -d, -confdir - A directory with config files. Multiple assign is accepted. - - -r - Load confdir recursively. - - -format - Format of config input. (default "auto") - - -pprof - HTTP server port for pprof debugging. (default "8080") - -Examples: - - {{.Exec}} {{.LongName}} -c config.json - {{.Exec}} {{.LongName}} -d path/to/dir - -Use "{{.Exec}} help format-loader" for more information about format. - `, - Run: executeRun, -} - -func executeRun(cmd *base.Command, args []string) { - setConfigFlags(cmd) - pprof := cmd.Flag.String("pprof", ":8080", "") - cmd.Flag.Parse(args) - printVersion() - configFiles = getConfigFilePath() - server, err := startV2Ray() - if err != nil { - base.Fatalf("Failed to start: %s", err) - } - - if addr := *pprof; addr != "" { - go func() { - if err := http.ListenAndServe(addr, nil); err != nil { - log.Print(err) - } - }() - } - - if err := server.Start(); err != nil { - base.Fatalf("Failed to start: %s", err) - } - defer server.Close() - - // Explicitly triggering GC to remove garbage from config loading. - runtime.GC() - - { - osSignals := make(chan os.Signal, 1) - signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM) - <-osSignals - } -} diff --git a/main/plugins/plugin.go b/main/plugins/plugin.go new file mode 100644 index 00000000000..58786b00ab6 --- /dev/null +++ b/main/plugins/plugin.go @@ -0,0 +1,11 @@ +package plugins + +import "github.com/v2fly/v2ray-core/v5/main/commands/base" + +var Plugins []Plugin + +type Plugin func(*base.Command) func() error + +func RegisterPlugin(plugin Plugin) { + Plugins = append(Plugins, plugin) +} diff --git a/main/plugins/plugin_pprof.go b/main/plugins/plugin_pprof.go new file mode 100644 index 00000000000..85f3bf76331 --- /dev/null +++ b/main/plugins/plugin_pprof.go @@ -0,0 +1,28 @@ +package plugins + +import ( + "net/http" + "net/http/pprof" + + "github.com/v2fly/v2ray-core/v5/main/commands/base" +) + +var pprofPlugin Plugin = func(cmd *base.Command) func() error { + addr := cmd.Flag.String("pprof", "", "") + return func() error { + if *addr != "" { + h := http.NewServeMux() + h.HandleFunc("/debug/pprof/", pprof.Index) + h.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) + h.HandleFunc("/debug/pprof/profile", pprof.Profile) + h.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + h.HandleFunc("/debug/pprof/trace", pprof.Trace) + return (&http.Server{Addr: *addr, Handler: h}).ListenAndServe() + } + return nil + } +} + +func init() { + RegisterPlugin(pprofPlugin) +} From 3382952c37df32baf23c9224f07bde20db973f43 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Fri, 6 Sep 2024 15:11:56 +0100 Subject: [PATCH 4/4] Adjust default build set to remove pprof from default distribution --- main/distro/all/all.go | 1 - main/plugins/{ => plugin_pprof}/plugin_pprof.go | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename main/plugins/{ => plugin_pprof}/plugin_pprof.go (76%) diff --git a/main/distro/all/all.go b/main/distro/all/all.go index 200f1228304..52b308523a8 100644 --- a/main/distro/all/all.go +++ b/main/distro/all/all.go @@ -33,7 +33,6 @@ import ( // Developer preview features _ "github.com/v2fly/v2ray-core/v5/app/instman" _ "github.com/v2fly/v2ray-core/v5/app/observatory" - _ "github.com/v2fly/v2ray-core/v5/app/restfulapi" _ "github.com/v2fly/v2ray-core/v5/app/tun" // Inbound and outbound proxies. diff --git a/main/plugins/plugin_pprof.go b/main/plugins/plugin_pprof/plugin_pprof.go similarity index 76% rename from main/plugins/plugin_pprof.go rename to main/plugins/plugin_pprof/plugin_pprof.go index 85f3bf76331..5da1a7b75c7 100644 --- a/main/plugins/plugin_pprof.go +++ b/main/plugins/plugin_pprof/plugin_pprof.go @@ -1,13 +1,14 @@ -package plugins +package plugin_pprof import ( + "github.com/v2fly/v2ray-core/v5/main/plugins" "net/http" "net/http/pprof" "github.com/v2fly/v2ray-core/v5/main/commands/base" ) -var pprofPlugin Plugin = func(cmd *base.Command) func() error { +var pprofPlugin plugins.Plugin = func(cmd *base.Command) func() error { addr := cmd.Flag.String("pprof", "", "") return func() error { if *addr != "" { @@ -24,5 +25,5 @@ var pprofPlugin Plugin = func(cmd *base.Command) func() error { } func init() { - RegisterPlugin(pprofPlugin) + plugins.RegisterPlugin(pprofPlugin) }