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