I have written a cli tool in go. When the cli tool is invoked via the terminal, i want the tool to wait for a Ctrl C interrupt(SIGINT) before calling a cleanup() function, before finally exiting.
however, as well as handling SIGINT, i also want the tool to handle cases where the terminal window is simply closed by the user. if its closed, i want the same cleanup function to be called. Here is a sample of what i tried.
package main
import (
"fmt"
"os"
"syscall"
"os/signal"
"os/exec"
"github.com/sirupsen/logrus"
)
func main() {
// Parse the command-line argument.
if len(os.Args) < 2 {
logrus.Fatalf("Missing required argument")
}
arg := os.Args[1]
logrus.Infof("Running with argument: %s", arg)
// Set up signal handling.
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
done := make(chan bool, 1)
go func() {
sig := <-signals
fmt.Println("")
fmt.Println("Disconnection requested via Ctrl C", sig)
done <- true
}()
logrus.Infof("Press Ctrl C to disconnect.")
<-done
cleanup()
os.Exit(0)
}
func cleanup() {
fmt.Println("Performing cleanup tasks...")
touchFile := exec.Command("touch", "testfile.txt",)
_, err := touchFile.CombinedOutput()
if err != nil {
println(err)
}
}
This works for cases where the user sends an interrupt via Ctrl C and the cleanup function is called, but the cleanup function is never called when the user simply just closes the window. I though the inclusion of syscall.SIGHUP
would work for this. please advise.
Edit: i've tested this in the default MacOS terminal, and the cleanup function is called when closing the window, but not when using iTerm.
CodePudding user response:
package main
import (
redacted
)
func main() {
// Parse the command-line argument.
if len(os.Args) < 2 {
logrus.Fatalf("Missing required argument")
}
arg := os.Args[1]
log.Infof("Running with argument: %s", arg)
// Set up signal handling.
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
done := make(chan bool, 1)
go func() {
sig := <-signals
fmt.Println("")
fmt.Println("Disconnection requested via Ctrl C", sig)
done <- true
}()
log.Infof("Press Ctrl C to disconnect.")
<-done
cleanup()
os.Exit(0)
}
func cleanup() {
fmt.Println("Performing cleanup tasks...")
touchFile := exec.Command("touch", "testfile.txt",)
_, err := touchFile.CombinedOutput()
if err != nil {
println(err)
}
}
The addition of SIGKILL works now for iTerm.