Skip to content

Instantly share code, notes, and snippets.

@jasisk
Created August 21, 2019 21:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jasisk/7638ba9b47c22b92214d5e354da047ac to your computer and use it in GitHub Desktop.
Save jasisk/7638ba9b47c22b92214d5e354da047ac to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"os"
"os/exec"
"os/signal"
"syscall"
)
func main() {
args := os.Args[1:]
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan)
for {
cmd := exec.Command(args[0], args[1:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true, Pgid: 0}
if err := cmd.Start(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
waitCh := make(chan error, 1)
go func() {
waitCh <- cmd.Wait()
close(waitCh)
}()
signalLoop:
for {
select {
case sig := <-sigChan:
switch sig {
case syscall.SIGUSR2:
fmt.Fprintln(os.Stderr, "Caught SIGUSR2, restarting ...")
if err := cmd.Process.Signal(syscall.SIGTERM); err != nil {
fmt.Fprintln(os.Stderr, "SIGTERM to child failed ...")
}
status := <-waitCh
if exitError, ok := status.(*exec.ExitError); ok {
_ = exitError.Sys().(syscall.WaitStatus)
}
break signalLoop
default:
if err := cmd.Process.Signal(sig); err != nil {
fmt.Fprintln(os.Stderr, "Signal to child failed ...")
}
}
case err := <-waitCh:
var waitStatus syscall.WaitStatus
if exitError, ok := err.(*exec.ExitError); ok {
waitStatus = exitError.Sys().(syscall.WaitStatus)
os.Exit(waitStatus.ExitStatus())
}
if err != nil {
fmt.Fprintln(os.Stderr, "Non-ok exit, oops")
}
return
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment