Skip to content

Instantly share code, notes, and snippets.

@lummie
Created September 21, 2023 17:27
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 lummie/0d58355d57b2fb830e71af06567fff2e to your computer and use it in GitHub Desktop.
Save lummie/0d58355d57b2fb830e71af06567fff2e to your computer and use it in GitHub Desktop.
Wait for graceful exit.. [k8s, pod, cli]
/*
Waits for a terminate | interrupt signal, ctrl-c before finishing main
when creating services and adapters, I like to return a cleanup function that is deferred for
each service, thus when the app closes they are teared down in reverse order.
graceful.Exit() returns two functions:
- waitFor - which is called as the last statement of main. This will block until a signal to terminate or interrupt the executable.
- deferMe - defer this first before the service cleanups. This ensures thar stdout/err are flushed and sleeps 1 second before exiting.
usage:
func main() {
waitFor, deferMe := graceful.Exit()
defer deferMe()
cleanupS1 := service1()
defer cleanupS1
...
cleanupSx := serviceX()
defer cleanupSx
waitFor()
}
*/
package graceful
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
)
// Exit returns two functions, waitFor will block until a terminate/interrupt signal is received, deferMe will flush std streams and delay termination
// see package for example usage.
func Exit() (waitFor func(), deferMe func()) {
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)
return func() {
sType := <-signalCh // wait for a signal
fmt.Printf("\n>> %s received, shutting down...\n", sType)
}, func() {
// make sure logs are flushed etc
os.Stdout.Sync()
os.Stderr.Sync()
time.Sleep(1 * time.Second)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment