diff --git a/main.go b/main.go index 45f2fb4..32ab108 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "encoding/json" + "errors" "flag" "fmt" "io" @@ -15,6 +16,12 @@ import ( "golang.org/x/sys/unix" ) +var ch chan struct{} + +func init() { + ch = make(chan struct{}) +} + type Service struct { CMD string `json:"cmd"` Args []string `json:"args"` @@ -31,9 +38,9 @@ func printErr(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) -} +// func printInfo(info string) { +// fmt.Fprintf(os.Stderr, "[qini] Inf: %s\n", info) +// } var verbose bool @@ -60,27 +67,31 @@ 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) int { +func runServices(services []*Service) error { if len(services) == 0 { - printInfo("no services in config") - return 1 + return errors.New("no services in config") } var ( r *io.PipeReader w *io.PipeWriter - - lock sync.Mutex - once sync.Once - wg sync.WaitGroup - - exitCode int ) - lock.Lock() - for i, s := range services { s.cmd = exec.Command(s.CMD, s.Args...) @@ -103,42 +114,20 @@ func runServices(services []*Service) int { s.cmd.Stdout = os.Stdout } - wg.Add(1) - go func(w *io.PipeWriter) { - defer wg.Done() + debug("run service [%s]", s.CMD) + err := s.cmd.Start() + if err != nil { + printErr(err) + } - defer func() { - if w != nil { - w.Close() - } - - once.Do(func() { - lock.Lock() - defer lock.Unlock() - - debug("stop all services") - - stopAllServices(services) - exitCode = s.cmd.ProcessState.ExitCode() - }) - }() - - debug("run service [%s]", s.CMD) - err := s.cmd.Run() - if err != nil { - printErr(err) - } - debug("service [%s] done, err: [%v]", s.CMD, err) - }(w) + go func(s *Service, w *io.PipeWriter) { + s.cmd.Wait() + w.Close() + debug("service done [%s]", s.CMD) + }(s, w) } - lock.Unlock() - - debug("wait servises") - wg.Wait() - debug("all servises stoped") - - return exitCode + return nil } func loadConfig(cfg *Config, configFile string) error { @@ -172,18 +161,24 @@ func forwardSignals2(services []*Service) { sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGCHLD) - for _ = range sigCh { - printInfo("chld") - for _, c := range services { - if c.cmd.ProcessState != nil { + 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) + }) } } } } func main() { - verbose = true + verbose = false err := unix.Prctl(unix.PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) if err != nil { @@ -192,6 +187,7 @@ func main() { var configFile string flag.StringVar(&configFile, "c", "./config.json", "JSON config file") + flag.BoolVar(&verbose, "v", false, "Show debug output") flag.Parse() var cfg Config @@ -205,6 +201,8 @@ func main() { go forwardSignals(cfg.Services) go forwardSignals2(cfg.Services) - exitCode := runServices(cfg.Services) - os.Exit(exitCode) + runServices(cfg.Services) + //os.Exit(exitCode) + + <-ch }