A lightweight Go library that provides utilities for graceful application shutdown handling, particularly useful for long-running services and daemons.
- Signal Handling: Automatically handles SIGINT (Ctrl-C) and SIGTERM signals
- Graceful Shutdown: Executes registered cleanup functions in LIFO order
- Error Management: Propagate fatal errors that should trigger application shutdown
- Concurrency Support: Run background goroutines that can trigger shutdown on error
go get github.com/KarpelesLab/shutdown
import (
"net"
"log/slog"
"github.com/KarpelesLab/shutdown"
)
func main() {
// Setup signal handlers early in your application
shutdown.SetupSignals()
// Run your application components
go launchHttp()
// Example of running multiple background tasks with error handling
shutdown.Go(
task1,
task2,
// More tasks...
)
// Wait for shutdown (this should be the last call in main)
shutdown.Wait()
}
func launchHttp() {
l, err := net.Listen("tcp", ":8080")
if err != nil {
// Report fatal errors that should trigger shutdown
shutdown.Fatalf("failed to listen for the http server: %w", err)
return
}
// Register cleanup functions to be executed during shutdown
shutdown.Defer(func() {
slog.Info("Closing HTTP listener")
l.Close()
})
// Your HTTP server implementation...
}
// Example task function that returns an error
func task1() error {
// If this returns an error, it will trigger shutdown
return nil
}
SetupSignals()
: Configures signal handlers for graceful shutdown (call early in main)Defer(func())
: Registers cleanup functions to be executed during shutdown (LIFO order)Fatalf(format, args...)
: Reports a fatal error that triggers shutdownGo(funcs ...func() error)
: Runs functions in background goroutines, errors trigger shutdownShutdown()
: Manually triggers the shutdown processWait()
: Blocks until shutdown is triggered, then runs cleanup functions (call last in main)
Shutdown can be triggered in several ways:
- OS Signals (SIGINT/Ctrl-C or SIGTERM)
- Fatal errors reported via
Fatalf()
- Errors returned from functions started with
Go()
- Manual trigger via
Shutdown()
When shutdown is triggered, all functions registered with Defer()
are executed in LIFO order (last registered, first executed).
See LICENSE file.