// Lock creates a lockfile which prevents to open more than one instance // of the same node (on the same machine). func (ctx *Context) Lock() (err error) { var f *os.File var p *os.Process var pid int lockFile := path.Join(ctx.storageDir, ctx.nodeName+".lock") if f, err = os.Open(lockFile); err != nil { goto lock } if _, err = fmt.Fscanf(f, "%d", &pid); err != nil && pid == 0 { goto lock } if p, err = os.FindProcess(pid); err == nil && p != nil { if err = p.Signal(os.UnixSignal(0)); err == nil { return errors.New( fmt.Sprintf("node '%s' is already running", ctx.NodeName())) } } lock: // Write a lock file. if f, err = os.Create(lockFile); err == nil { pid := os.Getppid() f.Write([]byte(fmt.Sprintf("%d", pid))) f.Close() } return nil }
func babySit(process *os.Process) int { // Forward all signals to the app sigchan := make(chan os.Signal, 1) sigutil.CatchAll(sigchan) go func() { for sig := range sigchan { if sig == syscall.SIGCHLD { continue } process.Signal(sig) } }() // Wait for the app to exit. Also, as pid 1 it's our job to reap all // orphaned zombies. var wstatus syscall.WaitStatus for { pid, err := syscall.Wait4(-1, &wstatus, 0, nil) if err == nil && pid == process.Pid { break } } return wstatus.ExitStatus() }
func checkstatus(p *os.Process, pname string, timest string) bool { fmt.Println("checkstatus", pname, p) reportlog[timest]["status"] = pname + " running" reportlog[timest][pname+"start"] = time.Now().Format("20060102150405") liner, _ := json.Marshal(reportlog) ioutil.WriteFile("static/data/reportlog.json", liner, 0) pw, _ := p.Wait() fmt.Println("checkstatus over", p) fmt.Println("timest=", timest) reportlog[timest][pname+"stop"] = time.Now().Format("20060102150405") t1, _ := time.Parse("20060102150405", reportlog[timest][pname+"stop"]) t2, _ := time.Parse("20060102150405", reportlog[timest][pname+"start"]) reportlog[timest][pname+"time"] = strconv.Itoa(int(t1.Sub(t2)) / 1e9) fmt.Println("t1=", t1) fmt.Println("t2=", t2) fmt.Println("cost=", t1.Sub(t2)) status := pw.Success() if status == true { reportlog[timest]["status"] = pname + " success" fmt.Println("checkstatus over success ", pname, p) } else { reportlog[timest]["status"] = pname + " failed" fmt.Println("checkstatus over failed ", pname, p) } liner, _ = json.Marshal(reportlog) ioutil.WriteFile("static/data/reportlog.json", liner, 0) return status }
func stopServer(proc *os.Process) { err := proc.Kill() if err != nil { panic(err.Error()) } proc.Release() }
func babySit(process *os.Process) int { log := logger.New("fn", "babySit") // Forward all signals to the app sigchan := make(chan os.Signal, 1) sigutil.CatchAll(sigchan) go func() { for sig := range sigchan { log.Info("received signal", "type", sig) if sig == syscall.SIGCHLD { continue } log.Info("forwarding signal to command", "type", sig) process.Signal(sig) } }() // Wait for the app to exit. Also, as pid 1 it's our job to reap all // orphaned zombies. var wstatus syscall.WaitStatus for { pid, err := syscall.Wait4(-1, &wstatus, 0, nil) if err == nil && pid == process.Pid { break } } if wstatus.Signaled() { log.Info("command exited due to signal") return 0 } return wstatus.ExitStatus() }
func signalProcess(process *os.Process, sig ssh.Signal) error { signal := msgs.Signals[sig] defer trace.End(trace.Begin(fmt.Sprintf("signal process %d: %s", process.Pid, sig))) s := syscall.Signal(signal) return process.Signal(s) }
// Lock creates a lockfile which prevents to open more than one instance // of the same node (on the same machine). func (ctx *Context) Lock() (err error) { var f *os.File var p *os.Process var pid int lockFile := path.Join(ctx.storageDir, ctx.nodeName+".lock") if f, err = os.Open(lockFile); err != nil { goto lock } if _, err = fmt.Fscanf(f, "%d", &pid); err != nil && pid == 0 { goto lock } if p, err = os.FindProcess(pid); err == nil && p != nil { if err = p.Signal(syscall.Signal(0)); err == nil { msg := fmt.Sprintf("node '%s' is already running", ctx.NodeName()) return errors.New(msg) } } lock: // Write a lock file. pidstr := []byte(fmt.Sprintf("%d", os.Getppid())) if err = ioutil.WriteFile(lockFile, pidstr, 0644); err != nil { return } return nil }
// Return the output from running the given command func GetOutput(args []string) (output string, error error) { var ( buffer *bytes.Buffer process *os.Process ) read_pipe, write_pipe, err := os.Pipe() if err != nil { goto Error } defer read_pipe.Close() process, err = os.StartProcess(args[0], args, &os.ProcAttr{ Dir: ".", Env: os.Environ(), Files: []*os.File{nil, write_pipe, nil}, }) if err != nil { write_pipe.Close() goto Error } _, err = process.Wait(0) write_pipe.Close() if err != nil { goto Error } buffer = &bytes.Buffer{} _, err = io.Copy(buffer, read_pipe) if err != nil { goto Error } output = buffer.String() return output, nil Error: return "", &CommandError{args[0], args} }
func runprog(argv []string) (filesize int64, mem int64, err error) { var attr os.ProcAttr var stat *os.ProcessState var proc *os.Process exepath, err := exec.LookPath(argv[0]) if err != nil { err = errors.New("can't find exe file.") return } proc, err = os.StartProcess(exepath, argv, &attr) if err != nil { return } fi, err := os.Stat(exepath) if err != nil { return } filesize = fi.Size() stat, err = proc.Wait() mem = int64(stat.SysUsage().(*syscall.Rusage).Maxrss) return }
func main() { flag.Parse() // done is sent a value when the analyzer should exit done := make(chan struct{}, 1) defer func() { done <- struct{}{} }() analyzerBin, analyzerArgs, compilations := parseAnalyzerCommand() if len(compilations) == 0 { flagutil.UsageError("Missing kindex-file paths") } cmd := exec.Command(analyzerBin, analyzerArgs...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr var proc *os.Process if err := process.StartAsync(cmd, &process.Callbacks{ OnStart: func(p *os.Process) { log.Printf("Starting analyzer subprocess: %s", strings.Join(cmd.Args, " ")) proc = p }, OnExit: func(state *os.ProcessState, err error) { select { case <-done: default: log.Fatalf("Analyzer subprocess exited unexpectedly (state:%v; error:%v)", state, err) } }, }); err != nil { log.Fatalf("Error starting analyzer: %v", err) } addr := fmt.Sprintf("localhost:%d", *analyzerPort) conn, err := grpc.Dial(addr, grpc.WithInsecure()) if err != nil { log.Fatalf("Error dialing analyzer %q: %v", addr, err) } defer conn.Close() queue := local.NewKIndexQueue(compilations) fdsAddr := launchFileDataService(queue) wr := delimited.NewWriter(os.Stdout) driver := &driver.Driver{ Analyzer: &remote.Analyzer{aspb.NewCompilationAnalyzerClient(conn)}, Output: func(_ context.Context, out *apb.AnalysisOutput) error { return wr.Put(out.Value) }, FileDataService: fdsAddr, Compilations: queue, } if err := driver.Run(context.Background()); err != nil { log.Fatal(err) } if err := proc.Signal(os.Interrupt); err != nil { log.Fatalf("Failed to send interrupt to analyzer: %v", err) } }
// SignalProcess sends signal sig to process p func SignalProcess(p *os.Process, sig os.Signal) error { if p == nil { return syscall.ESRCH } err := p.Signal(sig) return err }
func (h *Hoverfly) stop(hoverflyDirectory HoverflyDirectory) error { if !h.isLocal() { return errors.New("hoverctl can not stop an instance of Hoverfly on a remote host") } pid, err := hoverflyDirectory.GetPid(h.AdminPort, h.ProxyPort) if err != nil { log.Debug(err.Error()) return errors.New("Could not read Hoverfly pid file") } if pid == 0 { return errors.New("Hoverfly is not running") } hoverflyProcess := os.Process{Pid: pid} err = hoverflyProcess.Kill() if err != nil { log.Info(err.Error()) return errors.New("Could not kill Hoverfly") } err = hoverflyDirectory.DeletePid(h.AdminPort, h.ProxyPort) if err != nil { log.Debug(err.Error()) return errors.New("Could not delete Hoverfly pid") } return nil }
// Trap will listen for all stop signals and pass them along to the given // process. func Trap(process *os.Process) { c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGINT, syscall.SIGKILL, syscall.SIGQUIT) go func() { process.Signal(<-c) }() }
func GetExitCodeProcess(proc *os.Process) (uint32, error) { err := proc.Signal(syscall.Signal(0)) if err != nil { return 0, err } return 259, nil }
func (ss *SubService) rerunner(rerunChan chan bool) { var proc *os.Process for rerun := range rerunChan { if !rerun { break } cmd := exec.Command(ss.binPath, ss.argv...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr startupTimer := time.NewTimer(RerunWait) cmd.Start() proc = cmd.Process // In another goroutine, wait for the process to complete and send a relaunch signal. // If this signal is sent after the stop signal, it is ignored. go func(proc *os.Process) { proc.Wait() select { case <-startupTimer.C: // we let it run long enough that it might not be a recurring error, try again rerunChan <- true default: // error happened too quickly - must be startup issue startupTimer.Stop() } }(proc) } proc.Kill() }
// Run the command in the given string and restart it after // a message was received on the buildDone channel. func runner(command string, buildDone <-chan struct{}) { var currentProcess *os.Process pipeChan := make(chan io.ReadCloser) go logger(pipeChan) for { <-buildDone if currentProcess != nil { if err := currentProcess.Kill(); err != nil { log.Fatal("Could not kill child process. Aborting due to danger of infinite forks.") } _, werr := currentProcess.Wait() if werr != nil { log.Fatal("Could not wait for child process. Aborting due to danger of infinite forks.") } } log.Println("Restarting the given command.") cmd, stdoutPipe, stderrPipe, err := startCommand(command) if err != nil { log.Fatal("Could not start command:", err) } pipeChan <- stdoutPipe pipeChan <- stderrPipe currentProcess = cmd.Process } }
func handleSignal(channel chan os.Signal, synapse *os.Process) { select { case sig := <-channel: log.Print("Got signal: ", sig) synapse.Signal(os.Interrupt) os.Exit(1) } }
// Go doesn't support signals in windows (pre Go 1.3) because windows doesn't have signals. // Windows implementation will use kill func stop(process *os.Process) error { err := process.Kill() if err != nil { log.Println("Error while sending SIG_DEATH to running server:", err) return err } return nil }
func status(proc *os.Process) *Status { status, err := proc.Wait() if err != nil { return ExitFailure } return NewStatus(int64(status.Sys().(windows.WaitStatus).ExitStatus())) }
// Log a call to os.Process.Signal. func logSignal(p *os.Process, sig os.Signal) error { log.Printf("sending signal %s to PID %d", sig, p.Pid) err := p.Signal(sig) if err != nil { log.Print(err) } return err }
// Log a call to os.Process.Kill. func logKill(p *os.Process) error { log.Printf("killing PID %d", p.Pid) err := p.Kill() if err != nil { log.Print(err) } return err }
func handleTerm(p *os.Process) { term := make(chan os.Signal) signal.Notify(term, syscall.SIGTERM) go func() { <-term p.Signal(syscall.SIGTERM) }() }
func simpleKill(p *os.Process) error { if p == nil { return nil } Log.Info("killing", "pid", p.Pid) defer recover() return p.Kill() }
// SendCommands sends active signals to the given process. func SendCommands(p *os.Process) (err error) { for _, sig := range signals() { if err = p.Signal(sig); err != nil { return } } return }
func status(proc *os.Process) *Status { status, err := proc.Wait() if err != nil { return ExitFailure } return NewStatus(status.Sys().(plan9.Waitmsg).Msg) }
// Interrupter will send the `InfoSignal` to the given process every interval. func Interrupter(process *os.Process, interval time.Duration) { go func() { for { time.Sleep(interval) process.Signal(InfoSignal) } }() }
func JoinProcess(proc *os.Process) int { status, err := proc.Wait() if err != nil { return -1 } return status.Sys().(syscall.WaitStatus).ExitStatus() }
// Go doesn't support signals in windows (pre Go 1.3) because windows doesn't have signals. // Non-windows implementation will use signals func stop(process *os.Process) error { err := process.Signal(os.Interrupt) if err != nil { log.Println("Error while sending SIGINT to running server:", err) return err } _, err = process.Wait() return err }
func notifyAlive(p *os.Process, waiter chan int) { for { if PRINT_INFO { fmt.Println("Notifying") } time.Sleep(time.Second) p.Signal(syscall.SIGHUP) } }
// DoAppSupervision TODO func DoAppSupervision(cmdArgs []string) { // Launch the user app var appProcess *os.Process appChan := make(chan error, 1) if len(cmdArgs) > 0 { log.Infof("Launching app '%s' with args '%s'", cmdArgs[0], strings.Join(cmdArgs[1:], " ")) cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Start() if err != nil { appChan <- err } else { appProcess = cmd.Process go func() { appChan <- cmd.Wait() }() } } // Intercept SIGTERM/SIGINT and stop sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT) for { select { case sig := <-sigChan: log.Infof("Intercepted signal '%s'", sig) if appProcess != nil { appProcess.Signal(sig) } else { Shutdown(0) } case err := <-appChan: exitCode := 0 if err == nil { log.Info("App terminated with exit code 0") } else { exitCode = 1 if exitErr, ok := err.(*exec.ExitError); ok { if waitStatus, ok := exitErr.Sys().(syscall.WaitStatus); ok { exitCode = waitStatus.ExitStatus() } log.Errorf("App terminated with exit code %d", exitCode) } else { log.Errorf("App failed to start: %v", err) } } Shutdown(exitCode) } } }