diff --git a/box.go b/box.go index d2d30637..adf72bbb 100644 --- a/box.go +++ b/box.go @@ -39,18 +39,20 @@ type Box struct { func New(ctx context.Context, options option.Options, platformInterface platform.Interface) (*Box, error) { createdAt := time.Now() - logOptions := common.PtrValueOrDefault(options.Log) + + experimentalOptions := common.PtrValueOrDefault(options.Experimental) + applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug)) var needClashAPI bool var needV2RayAPI bool - if options.Experimental != nil { - if options.Experimental.ClashAPI != nil && options.Experimental.ClashAPI.ExternalController != "" { - needClashAPI = true - } - if options.Experimental.V2RayAPI != nil && options.Experimental.V2RayAPI.Listen != "" { - needV2RayAPI = true - } + if experimentalOptions.ClashAPI != nil && experimentalOptions.ClashAPI.ExternalController != "" { + needClashAPI = true } + if experimentalOptions.V2RayAPI != nil && experimentalOptions.V2RayAPI.Listen != "" { + needV2RayAPI = true + } + + logOptions := common.PtrValueOrDefault(options.Log) var logFactory log.Factory var observableLogFactory log.ObservableFactory diff --git a/debug.go b/debug.go new file mode 100644 index 00000000..b6197420 --- /dev/null +++ b/debug.go @@ -0,0 +1,35 @@ +//go:build go1.19 + +package box + +import ( + "runtime/debug" + + "github.com/sagernet/sing-box/common/dialer/conntrack" + "github.com/sagernet/sing-box/option" +) + +func applyDebugOptions(options option.DebugOptions) { + if options.GCPercent != nil { + debug.SetGCPercent(*options.GCPercent) + } + if options.MaxStack != nil { + debug.SetMaxStack(*options.MaxStack) + } + if options.MaxThreads != nil { + debug.SetMaxThreads(*options.MaxThreads) + } + if options.PanicOnFault != nil { + debug.SetPanicOnFault(*options.PanicOnFault) + } + if options.TraceBack != "" { + debug.SetTraceback(options.TraceBack) + } + if options.MemoryLimit != 0 { + debug.SetMemoryLimit(int64(options.MemoryLimit)) + conntrack.MemoryLimit = int64(options.MemoryLimit) + } + if options.OOMKiller != nil { + conntrack.KillerEnabled = *options.OOMKiller + } +} diff --git a/debug_go118.go b/debug_go118.go new file mode 100644 index 00000000..88fdc05e --- /dev/null +++ b/debug_go118.go @@ -0,0 +1,35 @@ +//go:build !go1.19 + +package box + +import ( + "runtime/debug" + + "github.com/sagernet/sing-box/common/dialer/conntrack" + "github.com/sagernet/sing-box/option" +) + +func applyDebugOptions(options option.DebugOptions) { + if options.GCPercent != nil { + debug.SetGCPercent(*options.GCPercent) + } + if options.MaxStack != nil { + debug.SetMaxStack(*options.MaxStack) + } + if options.MaxThreads != nil { + debug.SetMaxThreads(*options.MaxThreads) + } + if options.PanicOnFault != nil { + debug.SetPanicOnFault(*options.PanicOnFault) + } + if options.TraceBack != "" { + debug.SetTraceback(options.TraceBack) + } + if options.MemoryLimit != 0 { + // debug.SetMemoryLimit(int64(options.MemoryLimit)) + conntrack.MemoryLimit = int64(options.MemoryLimit) + } + if options.OOMKiller != nil { + conntrack.KillerEnabled = *options.OOMKiller + } +} diff --git a/option/debug.go b/option/debug.go new file mode 100644 index 00000000..78318c23 --- /dev/null +++ b/option/debug.go @@ -0,0 +1,43 @@ +package option + +import ( + "encoding/json" + + "github.com/dustin/go-humanize" +) + +type DebugOptions struct { + GCPercent *int `json:"gc_percent,omitempty"` + MaxStack *int `json:"max_stack,omitempty"` + MaxThreads *int `json:"max_threads,omitempty"` + PanicOnFault *bool `json:"panic_on_fault,omitempty"` + TraceBack string `json:"trace_back,omitempty"` + MemoryLimit BytesLength `json:"memory_limit,omitempty"` + OOMKiller *bool `json:"oom_killer,omitempty"` +} + +type BytesLength int64 + +func (l BytesLength) MarshalJSON() ([]byte, error) { + return json.Marshal(humanize.IBytes(uint64(l))) +} + +func (l *BytesLength) UnmarshalJSON(bytes []byte) error { + var valueInteger int64 + err := json.Unmarshal(bytes, &valueInteger) + if err == nil { + *l = BytesLength(valueInteger) + return nil + } + var valueString string + err = json.Unmarshal(bytes, &valueString) + if err != nil { + return err + } + parsedValue, err := humanize.ParseBytes(valueString) + if err != nil { + return err + } + *l = BytesLength(parsedValue) + return nil +} diff --git a/option/experimental.go b/option/experimental.go index 2167ddaa..a5b6acbd 100644 --- a/option/experimental.go +++ b/option/experimental.go @@ -3,4 +3,5 @@ package option type ExperimentalOptions struct { ClashAPI *ClashAPIOptions `json:"clash_api,omitempty"` V2RayAPI *V2RayAPIOptions `json:"v2ray_api,omitempty"` + Debug *DebugOptions `json:"debug,omitempty"` }