82 lines
2.1 KiB
Go
82 lines
2.1 KiB
Go
//go:build !darwin || !cgo
|
|
|
|
package oomkiller
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/sagernet/sing-box/adapter"
|
|
boxService "github.com/sagernet/sing-box/adapter/service"
|
|
boxConstant "github.com/sagernet/sing-box/constant"
|
|
"github.com/sagernet/sing-box/log"
|
|
"github.com/sagernet/sing-box/option"
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
"github.com/sagernet/sing/common/memory"
|
|
"github.com/sagernet/sing/service"
|
|
)
|
|
|
|
func RegisterService(registry *boxService.Registry) {
|
|
boxService.Register[option.OOMKillerServiceOptions](registry, boxConstant.TypeOOMKiller, NewService)
|
|
}
|
|
|
|
type Service struct {
|
|
boxService.Adapter
|
|
logger log.ContextLogger
|
|
router adapter.Router
|
|
adaptiveTimer *adaptiveTimer
|
|
timerConfig timerConfig
|
|
hasTimerMode bool
|
|
useAvailable bool
|
|
memoryLimit uint64
|
|
}
|
|
|
|
func NewService(ctx context.Context, logger log.ContextLogger, tag string, options option.OOMKillerServiceOptions) (adapter.Service, error) {
|
|
s := &Service{
|
|
Adapter: boxService.NewAdapter(boxConstant.TypeOOMKiller, tag),
|
|
logger: logger,
|
|
router: service.FromContext[adapter.Router](ctx),
|
|
}
|
|
|
|
if options.MemoryLimit != nil {
|
|
s.memoryLimit = options.MemoryLimit.Value()
|
|
}
|
|
if s.memoryLimit > 0 {
|
|
s.hasTimerMode = true
|
|
} else if memory.AvailableSupported() {
|
|
s.useAvailable = true
|
|
s.hasTimerMode = true
|
|
}
|
|
|
|
config, err := buildTimerConfig(options, s.memoryLimit, s.useAvailable)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s.timerConfig = config
|
|
|
|
return s, nil
|
|
}
|
|
|
|
func (s *Service) Start(stage adapter.StartStage) error {
|
|
if stage != adapter.StartStateStart {
|
|
return nil
|
|
}
|
|
if !s.hasTimerMode {
|
|
return E.New("memory pressure monitoring is not available on this platform without memory_limit")
|
|
}
|
|
s.adaptiveTimer = newAdaptiveTimer(s.logger, s.router, s.timerConfig)
|
|
s.adaptiveTimer.start(0)
|
|
if s.useAvailable {
|
|
s.logger.Info("started memory monitor with available memory detection")
|
|
} else {
|
|
s.logger.Info("started memory monitor with limit: ", s.memoryLimit/(1024*1024), " MiB")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) Close() error {
|
|
if s.adaptiveTimer != nil {
|
|
s.adaptiveTimer.stop()
|
|
}
|
|
return nil
|
|
}
|