From 7c809a003883d72c066ae9a7a377a5c0e38920ae Mon Sep 17 00:00:00 2001 From: r-vdp Date: Mon, 18 Nov 2024 15:38:06 +0900 Subject: [PATCH] feat: propagate signals to launched subprocesses so that they can properly clean up resources --- command/cleanup.go | 39 ++++++++++++++++++++++++++++++++++++++- command/please.go | 21 +++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/command/cleanup.go b/command/cleanup.go index 2e84118..0f4af4a 100644 --- a/command/cleanup.go +++ b/command/cleanup.go @@ -7,8 +7,10 @@ import ( "log" "os" "os/exec" + "os/signal" "strconv" "strings" + "syscall" "github.com/google/go-github/github" cli "gopkg.in/urfave/cli.v1" @@ -71,7 +73,24 @@ func CmdCleanup(c *cli.Context) (err error) { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr + signalChannel := make(chan os.Signal, 1) + signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) + go func() { + for sig := range signalChannel { + if cmd.Process != nil { + err := cmd.Process.Signal(sig) + if err != nil { + log.Printf("error sending signal to child process (%d): %s\n", cmd.Process.Pid, err) + } + } else { + // TODO: is this always the right thing to do if we're not running a subprocess? + os.Exit(1) + } + } + }() + err = cmd.Run() + signal.Stop(signalChannel) if err != nil { log.Println("undeploy error: ", err) @@ -108,7 +127,25 @@ func listDeployedPullRequests(listScript string) ([]string, error) { cmd := exec.Command(listScript) cmd.Stdout = &stdout - if err := cmd.Run(); err != nil { + signalChannel := make(chan os.Signal, 1) + signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) + go func() { + for sig := range signalChannel { + if cmd.Process != nil { + err := cmd.Process.Signal(sig) + if err != nil { + log.Printf("error sending signal to child process (%d): %s\n", cmd.Process.Pid, err) + } + } else { + // TODO: is this always the right thing to do if we're not running a subprocess? + os.Exit(1) + } + } + }() + + err := cmd.Run() + signal.Stop(signalChannel) + if err != nil { return nil, err } diff --git a/command/please.go b/command/please.go index 9c0932b..5d6e713 100644 --- a/command/please.go +++ b/command/please.go @@ -9,8 +9,10 @@ import ( "log" "os" "os/exec" + "os/signal" "strconv" "strings" + "syscall" "github.com/google/go-github/github" cli "gopkg.in/urfave/cli.v1" @@ -151,6 +153,23 @@ func CmdPlease(c *cli.Context) (err error) { } // Start deploy script + signalChannel := make(chan os.Signal, 1) + signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) + go func() { + cmd := cmd + for sig := range signalChannel { + if cmd.Process != nil { + err := cmd.Process.Signal(sig) + if err != nil { + log.Printf("error sending signal to child process (%d): %s\n", cmd.Process.Pid, err) + } + } else { + // TODO: is this always the right thing to do if we're not running a subprocess? + os.Exit(1) + } + } + }() + err = cmd.Start() if err != nil { err2 := updateStatus(StateError, "") @@ -169,6 +188,8 @@ func CmdPlease(c *cli.Context) (err error) { // Wait on the deploy to finish err = cmd.Wait() + signal.Stop(signalChannel) + if err != nil { err2 := updateStatus(StateFailure, "") if err2 != nil {