Go: Graceful Shutdown

Handling OS signals and shutting down gracefully

Problem

It can sometimes be useful to run code before the application shuts down. This code could handle removing temporary files, flushing changes, etc.

While it is impossible to ensure this code is always executed (e.g. the system running the app could crash), it can be useful to add code to handle a graceful shutdown in the general case.

Solution

func main() {
	setupGracefulShutdown()
	// ...
}

func setupGracefulShutdown() {
	// Create chanel for OS signals
	var signals = make(chan os.Signal)

	// Configure which OS signals to be put in the chanel
	signal.Notify(signals, syscall.SIGTERM)
	signal.Notify(signals, syscall.SIGINT)

	// Listen for signals in the background
	go func() {
		sig := <-signals
		log.Printf("caught signal: %+v", sig)
		// TODO: anything necessary for a graceful shutdown
		os.Exit(0)
	}()
}

Details

In this context, "graceful shutdown" means giving the application code time to exit smoothly and correctly.

For example, this could include saving any internal cache out to a file/database, closing any open database connections, or completing any requests still in progress. It really depends on the application.

The code above introduces a location where all this code can be triggered just after an OS signal is received and just before the application closes down.