diff --git a/Makefile b/Makefile index 7cf022c..3152cf1 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,11 @@ - lint: .golangci.yml golangci-lint run +wait-demo: + # Doesn't work with tinygo (yet) because undefined symbol: _os/signal.signal_enable... + go run -tags no_net,no_json ./sampleTool/ -wait arg1 arg2 + .golangci.yml: Makefile curl -fsS -o .golangci.yml https://raw.githubusercontent.com/fortio/workflows/main/golangci.yml -.PHONY: lint +.PHONY: lint wait-demo diff --git a/cli.go b/cli.go index 8503330..cf0e5f3 100644 --- a/cli.go +++ b/cli.go @@ -17,8 +17,10 @@ import ( "fmt" "io" "os" + "os/signal" "path/filepath" "strings" + "syscall" "fortio.org/log" "fortio.org/version" @@ -253,3 +255,20 @@ func PluralExt(i int, noun string, ext string) string { } return noun + ext } + +// UntilInterrupted runs forever or until interrupted (ctrl-c or shutdown signal (kill -INT or -TERM)). +// Kubernetes for instance sends a SIGTERM before killing a pod. +// You can place your clean shutdown code after this call in the main(). +// This assumes there is another go routine doing something (like a server). +func UntilInterrupted() { + // if UntilInterrupted is called, it implies there should be another goroutine at least. + // so we put back that logging (vs what log.SetDefaultsForClientTools() does). + log.Config.GoroutineID = true + // listen for interrupt signal + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + // Block until a signal is received. + log.LogVf("Waiting for interrupt signal...") + <-c + log.Warnf("Interrupt received.") +} diff --git a/sampleTool/main.go b/sampleTool/main.go index 8902387..238864c 100644 --- a/sampleTool/main.go +++ b/sampleTool/main.go @@ -9,6 +9,8 @@ import ( func main() { myFlag := flag.String("myflag", "default", "my flag") + doWait := flag.Bool("wait", false, "wait for ^C before exiting") + cli.MinArgs = 2 cli.MaxArgs = 4 cli.Main() // Will have either called cli.ExitFunction or everything is valid @@ -21,4 +23,9 @@ func main() { log.Str("myflag", *myFlag), log.Attr("num_args", len(flag.Args())), log.Attr("args", flag.Args())) + if *doWait { + log.Infof("Waiting for ^C (or kill) to exit") + cli.UntilInterrupted() + log.Infof("Now done...") + } }