From a5055b226ffa77840d2e70675713c5acc5292708 Mon Sep 17 00:00:00 2001 From: "Timofey.Kovalev" Date: Fri, 25 Jul 2025 14:40:17 +0300 Subject: [PATCH] commit --- main.go | 107 ++++++++++++++++++++++++++------------------------------ 1 file changed, 50 insertions(+), 57 deletions(-) diff --git a/main.go b/main.go index 32ab108..6a2fa91 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,6 @@ import ( "errors" "flag" "fmt" - "io" "os" "os/exec" "os/signal" @@ -35,13 +34,9 @@ type Config struct { } func printErr(err error) { - fmt.Fprintf(os.Stderr, "[qini] Err: %s\n", err.Error()) + fmt.Fprintf(os.Stderr, "[qini] err: %s\n", err.Error()) } -// func printInfo(info string) { -// fmt.Fprintf(os.Stderr, "[qini] Inf: %s\n", info) -// } - var verbose bool func debug(s string, a ...any) { @@ -67,36 +62,29 @@ func stopAllServices(services []*Service) { } }(s) } - -loop: - for { - time.Sleep(time.Second) - - for _, s := range services { - if s.cmd.Process != nil && s.cmd.ProcessState == nil { - continue loop - } - } - - os.Exit(1) - } } -func runServices(services []*Service) error { +func runServices(services []*Service) (int, error) { if len(services) == 0 { - return errors.New("no services in config") + return 0, errors.New("no services in config") } var ( - r *io.PipeReader - w *io.PipeWriter + r *os.File + w *os.File + + once sync.Once + exitCode int + wg sync.WaitGroup + + err error ) for i, s := range services { s.cmd = exec.Command(s.CMD, s.Args...) s.cmd.SysProcAttr = &syscall.SysProcAttr{ - Setsid: false, + Setsid: true, } if s.PWD != "" { @@ -105,10 +93,16 @@ func runServices(services []*Service) error { if r != nil { s.cmd.Stdin = r + } else { + s.cmd.Stdin = os.Stdin } if i+1 < len(services) { - r, w = io.Pipe() + r, w, err = os.Pipe() + if err != nil { + return 0, err + } + s.cmd.Stdout = w } else { s.cmd.Stdout = os.Stdout @@ -120,14 +114,26 @@ func runServices(services []*Service) error { printErr(err) } - go func(s *Service, w *io.PipeWriter) { + wg.Add(1) + go func(s *Service, w *os.File) { + defer wg.Done() + s.cmd.Wait() w.Close() debug("service done [%s]", s.CMD) + + exitCode = s.cmd.ProcessState.ExitCode() + + once.Do(func() { + debug("stop all services") + stopAllServices(services) + }) }(s, w) } - return nil + wg.Wait() + + return exitCode, nil } func loadConfig(cfg *Config, configFile string) error { @@ -142,37 +148,22 @@ func loadConfig(cfg *Config, configFile string) error { } func forwardSignals(services []*Service) { - signals := []os.Signal{syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT} + signals := []os.Signal{syscall.SIGCHLD, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT} sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, signals...) for sig := range sigCh { - for _, s := range services { - if s.cmd.Process == nil { - continue - } - - syscall.Kill(s.cmd.Process.Pid, (sig).(syscall.Signal)) - } - } -} - -func forwardSignals2(services []*Service) { - sigCh := make(chan os.Signal, 1) - signal.Notify(sigCh, syscall.SIGCHLD) - - var once sync.Once - - for range sigCh { - debug("chld") - for _, c := range services { - debug("%v", c.cmd.ProcessState) - if c.cmd.ProcessState != nil { - once.Do(func() { - debug("stop all services") - stopAllServices(services) - }) + switch sig { + case syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT: + for _, s := range services { + if s.cmd.Process == nil { + continue + } + + syscall.Kill(s.cmd.Process.Pid, (sig).(syscall.Signal)) } + case syscall.SIGCHLD: + debug("chld") } } } @@ -199,10 +190,12 @@ func main() { } go forwardSignals(cfg.Services) - go forwardSignals2(cfg.Services) - runServices(cfg.Services) - //os.Exit(exitCode) + exitCode, err := runServices(cfg.Services) + if err != nil { + printErr(err) + os.Exit(123) + } - <-ch + os.Exit(exitCode) }