From 757058930842ff4a87df7137bbc2931e8f682a87 Mon Sep 17 00:00:00 2001 From: dnomd343 Date: Tue, 16 Aug 2022 17:02:37 +0800 Subject: [PATCH] update: daemon logical --- src/main.go | 52 +++++++++++---------------- src/process.go | 97 +++++++++++++++++++++++++++++++------------------- 2 files changed, 80 insertions(+), 69 deletions(-) diff --git a/src/main.go b/src/main.go index 36e176a..1e1e3b2 100644 --- a/src/main.go +++ b/src/main.go @@ -1,16 +1,12 @@ package main import ( - "fmt" log "github.com/sirupsen/logrus" + "os" + "os/signal" "syscall" - "time" ) -var xray *Process -var sleep *Process -var empty *Process - var logLevel = "warning" var v4RouteTable = 100 @@ -26,43 +22,35 @@ var addOnInbounds []interface{} var assetFile = "/etc/xproxy/assets.tar.xz" -func exit() { - log.Warningf("Start exit process") - xray.disableProcess() - xray.sendSignal(syscall.SIGTERM) - //log.Infof("Send kill signal to process %s", xray.caption) - sleep.disableProcess() - sleep.sendSignal(syscall.SIGTERM) - empty.disableProcess() - empty.sendSignal(syscall.SIGTERM) - log.Info("Wait sub process exit") - for !(xray.done && sleep.done) { - } - log.Infof("Exit complete") -} - func main() { + defer func() { + if err := recover(); err != nil { + log.Errorf("Unknown error -> %v", err) + } + }() log.SetLevel(log.DebugLevel) log.Warning("XProxy start") - xray = newProcess("xray", "-confdir", "/etc/xproxy/config") + xray := newProcess("xray", "-confdir", "/etc/xproxy/config") xray.startProcess(true, true) - sleep = newProcess("sleep", "1000") + sleep := newProcess("sleep", "1000") sleep.startProcess(true, true) - //done := make(chan bool, 1) + empty := newProcess("empty") + + subProcess = append(subProcess, xray) + subProcess = append(subProcess, sleep) + subProcess = append(subProcess, empty) - daemon(xray) - daemon(sleep) - daemon(empty) + for _, sub := range subProcess { + daemon(sub) + } - fmt.Println("start sleep...") - time.Sleep(10 * time.Second) - fmt.Println("wake up") + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + <-sigs exit() - - //<-done //content, err := os.ReadFile("test.yml") //if err != nil { diff --git a/src/process.go b/src/process.go index 6c322ac..429486d 100644 --- a/src/process.go +++ b/src/process.go @@ -5,22 +5,24 @@ import ( "os" "os/exec" "syscall" + "time" ) +var subProcess []*Process + type Process struct { - done bool enable bool - caption string + name string command []string process *exec.Cmd + exit bool } func newProcess(command ...string) *Process { process := new(Process) - process.enable = true + process.name = command[0] process.command = command - process.caption = command[0] - log.Debugf("New process %s -> %v", process.caption, process.command) + log.Debugf("New process %s -> %v", process.name, process.command) return process } @@ -32,57 +34,78 @@ func (p *Process) startProcess(isStdout bool, isStderr bool) { if isStderr { p.process.Stderr = os.Stderr } + p.enable = true err := p.process.Start() if err != nil { - log.Errorf("Failed to start %s -> %v", p.caption, err) + log.Errorf("Failed to start %s -> %v", p.name, err) } - log.Infof("Start process %s -> PID = %d", p.caption, p.process.Process.Pid) -} - -func (p *Process) isProcessAlive() bool { - return p.process.ProcessState == nil + log.Infof("Start process %s -> PID = %d", p.name, p.process.Process.Pid) } func (p *Process) sendSignal(signal syscall.Signal) { - if p != nil { - err := p.process.Process.Signal(signal) - if err != nil { - log.Errorf("Send signal %v to process %s error -> %v", signal, p.caption, err) - } + //defer func() { + // _ = recover() + //}() + if p.process != nil && p.process.ProcessState == nil { + log.Debugf("Send signal %v to %s", signal, p.name) + _ = p.process.Process.Signal(signal) } } func (p *Process) waitProcess() { - err := p.process.Wait() - if err != nil { - log.Warningf("Wait process %s -> %v", p.caption, err) - } -} - -func (p *Process) disableProcess() { - if p != nil { - p.enable = false + if p.process != nil { + err := p.process.Wait() + if err != nil { + log.Warningf("Wait process %s -> %v", p.name, err) + } } } func daemonSub(sub *Process) { - for sub.isProcessAlive() { + for sub.process.ProcessState == nil { sub.waitProcess() } - log.Warningf("Catch process %s exit", sub.caption) - if sub.enable { - sub.startProcess(true, true) - log.Infof("Process %s restart success", xray.caption) - daemonSub(sub) + log.Warningf("Catch process %s exit", sub.name) + if !sub.enable { + log.Debugf("Process %s disabled -> stop daemon", sub.name) + return } + sub.startProcess(true, true) + log.Infof("Process %s restart success", sub.name) + daemonSub(sub) } func daemon(sub *Process) { - if sub != nil && sub.enable { - log.Infof("Start daemon of process %s", sub.caption) - go func() { - daemonSub(sub) - sub.done = true - }() + if !sub.enable { + log.Infof("Process %s disabled -> skip daemon", sub.name) + sub.exit = true + return + } + log.Infof("Start daemon of process %s", sub.name) + go func() { + daemonSub(sub) + log.Infof("Process %s daemon exit", sub.name) + sub.exit = true + }() +} + +func exit() { + log.Warningf("Start exit process") + for _, sub := range subProcess { + sub.enable = false + if sub.process != nil { + sub.sendSignal(syscall.SIGTERM) + log.Infof("Send kill signal to process %s", sub.name) + } + } + var allExit bool + log.Info("Wait all sub process exit") + for !allExit { + time.Sleep(10 * time.Millisecond) // delay 10ms + allExit = true + for _, sub := range subProcess { + allExit = allExit && sub.exit //(sub.process.ProcessState != nil) + } } + log.Infof("Exit complete") }