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) }
// 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 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 GetExitCodeProcess(proc *os.Process) (uint32, error) { err := proc.Signal(syscall.Signal(0)) if err != nil { return 0, err } return 259, nil }
func run(ch chan bool, bin string, args []string) { go func() { var proc *os.Process for relaunch := range ch { if proc != nil { if err := proc.Signal(os.Interrupt); err != nil { proc.Kill() } proc.Wait() } if !relaunch { continue } cmd := exec.Command(bin, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Start(); err != nil { log("error: %s", err) } proc = cmd.Process } }() 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 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() }
// runBin runs the generated bin file with the arguments expected func runBin(bindir, bin string, args []string) chan bool { var relunch = make(chan bool) go func() { binfile := fmt.Sprintf("%s/%s", bindir, bin) // cmdline := append([]string{bin}, args...) var proc *os.Process for dosig := range relunch { if proc != nil { if err := proc.Signal(os.Interrupt); err != nil { log.Printf("Error in sending signal %s", err) proc.Kill() } proc.Wait() } if !dosig { continue } cmd := exec.Command(binfile, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Start(); err != nil { log.Printf("Error starting process: %s", err) } proc = cmd.Process } }() return relunch }
func run(binName, binPath string, args []string) (runch chan bool) { runch = make(chan bool) go func() { cmdline := append([]string{binName}, args...) var proc *os.Process for relaunch := range runch { if proc != nil { err := proc.Signal(os.Interrupt) if err != nil { log.Printf("error on sending signal to process: '%s', will now hard-kill the process\n", err) proc.Kill() } proc.Wait() } if !relaunch { continue } cmd := exec.Command(binPath, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr log.Print(cmdline) err := cmd.Start() if err != nil { log.Printf("error on starting process: '%s'\n", err) } proc = cmd.Process } }() return }
// 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 }
// 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 handleSignal(channel chan os.Signal, synapse *os.Process) { select { case sig := <-channel: log.Print("Got signal: ", sig) synapse.Signal(os.Interrupt) os.Exit(1) } }
// 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) } }() }
// 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 }
// 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 handleTerm(p *os.Process) { term := make(chan os.Signal) signal.Notify(term, syscall.SIGTERM) go func() { <-term p.Signal(syscall.SIGTERM) }() }
// RunGo runs the generated binary file with the arguments expected func RunGo(gofile string, args []string, done, stopped func()) chan bool { var relunch = make(chan bool) // if runtime.GOOS == "windows" { gofile = filepath.Clean(gofile) // } go func() { // var cmdline = fmt.Sprintf("go run %s", gofile) cmdargs := append([]string{"run", gofile}, args...) // cmdline = strings.Joinappend([]string{}, "go run", gofile) var proc *os.Process for dosig := range relunch { if proc != nil { var err error if runtime.GOOS == "windows" { err = proc.Kill() } else { err = proc.Signal(os.Interrupt) } if err != nil { fmt.Printf("---> Error in Sending Kill Signal %s\n", err) proc.Kill() } proc.Wait() proc = nil } if !dosig { continue } fmt.Printf("--> Starting cmd: %s\n", cmdargs) cmd := exec.Command("go", cmdargs...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Start(); err != nil { fmt.Printf("---> Error starting process: %s\n", err) } proc = cmd.Process if done != nil { done() } } if stopped != nil { stopped() } }() return relunch }
func notifyAlive(p *os.Process, waiter chan int) { for { if PRINT_INFO { fmt.Println("Notifying") } time.Sleep(time.Second) p.Signal(syscall.SIGHUP) } }
// 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 }
// 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) } } }
// Attempts to shut down a process gracefully. // There's an obvious race condition here; if we succeed with SIGTERM and // somebody else gets the same pid in 10 seconds, we'll SIGKILL them. // Unlikely in most cases? TODO(gaal): maybe add a way for a caller tor // signal to us that Wait succeeded. func shutdown(process *os.Process) { process.Signal(syscall.SIGTERM) go func() { time.Sleep(10e9) if _, err := os.FindProcess(process.Pid); err == nil { process.Signal(syscall.SIGKILL) // == process.Kill() } }() }
func waitForProc(proc *os.Process) bool { var err error // Check every 100 ms up to 100 times (10s total) for i := 0; err == nil && i < 100; i++ { time.Sleep(100 * time.Millisecond) err = proc.Signal(syscall.Signal(0)) } return err != nil }
func watch() { app := core.NewApp("sarif", "tars") app.Init() info := Cache{FilePath: app.Config.Dir() + "/soji.json"} info.Bars = make(map[string]Bar) info.Read() err := info.Read() if err == nil { if info.PID > 0 { var p *os.Process p, err = os.FindProcess(info.PID) if err == nil { err = p.Signal(syscall.Signal(0)) } } else { err = errors.New("PID not found") } } if err != nil { fork(app) return } mode := "" if *isTmux { mode = "tmux" } keys := make([]string, 0, len(info.Bars)) if len(flag.Args()) > 0 { keys = flag.Args() } else { for key := range info.Bars { keys = append(keys, key) } sort.Strings(keys) } texts := make([]string, 0) for _, key := range keys { bar, ok := info.Bars[key] if !ok { continue } text := bar.PrettyString(mode) if text != "" { texts = append(texts, text) } } fmt.Println(strings.Join(texts, *delimiter)) }
func killCamli(proc *os.Process) { if *fast { return } dbg.Println("killing dev server") err := proc.Signal(os.Interrupt) if err != nil { log.Fatalf("Could not kill server: %v", err) } dbg.Println("") }
func sendSignalToProcess(process *os.Process, what values.Signal, tryGroup bool) error { if tryGroup { pgid, err := syscall.Getpgid(process.Pid) if err == nil { if syscall.Kill(-pgid, syscall.Signal(what)) == nil { return nil } } } process.Signal(syscall.Signal(what)) return nil }
func endProcess(p *os.Process) error { if p == nil { return nil } if err := p.Signal(syscall.SIGTERM); err != nil { return err } _, err := p.Wait() if *verbose { log.Printf("Exiting pid %d.", p.Pid) } return err }
func groupKill(p *os.Process, interrupt bool) error { if p == nil { return nil } Log.Info("groupKill", "pid", p.Pid) defer recover() if interrupt { defer p.Signal(os.Interrupt) return GroupKill(p.Pid, os.Interrupt) } defer p.Kill() return GroupKill(p.Pid, os.Kill) }
func (d *Daemon) handle(input link.Input, process *os.Process, stdin *os.File) error { if input.WindowSize != nil { setWinSize(stdin, input.WindowSize.Columns, input.WindowSize.Rows) process.Signal(syscall.SIGWINCH) } else if input.EOF { stdin.Sync() err := stdin.Close() if d.WithTty { process.Signal(syscall.SIGHUP) } if err != nil { return err } } else if input.Signal != nil { if input.Signal.Signal == garden.SignalTerminate { process.Signal(syscall.SIGTERM) } else if input.Signal.Signal == garden.SignalKill { process.Signal(syscall.SIGKILL) } } else { _, err := stdin.Write(input.StdinData) if err != nil { return err } } return nil }
// RunBin runs the generated binary file with the arguments expected func RunBin(binfile string, args []string, done, stopped func()) chan bool { var relunch = make(chan bool) go func() { // binfile := fmt.Sprintf("%s/%s", bindir, bin) // cmdline := append([]string{bin}, args...) var proc *os.Process for dosig := range relunch { if proc != nil { var err error if runtime.GOOS == "windows" { err = proc.Kill() } else { err = proc.Signal(os.Interrupt) } if err != nil { fmt.Printf("---> Error in Sending Kill Signal: %s\n", err) proc.Kill() } proc.Wait() proc = nil } if !dosig { continue } fmt.Printf("--> Starting bin: %s\n", binfile) cmd := exec.Command(binfile, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Start(); err != nil { fmt.Printf("---> Error starting process: %s -> %s\n", binfile, err) } proc = cmd.Process if done != nil { done() } } if stopped != nil { stopped() } }() return relunch }