Hone logo
Hone
Problems

Graceful Shutdown: Implementing Signal Handling in Go

Applications often need to respond to external signals, such as requests to shut down gracefully. Implementing signal handling allows your Go program to catch these signals, perform necessary cleanup operations, and exit in a controlled manner, preventing data loss or corruption. This challenge focuses on building a robust signal handling mechanism in a Go application.

Problem Description

Your task is to create a Go program that simulates a long-running process and implements graceful shutdown using signal handling. The program should:

  1. Simulate a long-running process: This can be achieved by having a goroutine that periodically performs some work (e.g., printing a message, incrementing a counter) and sleeps for a short duration.
  2. Listen for operating system signals: Specifically, your program should listen for SIGINT (interrupt signal, typically sent by Ctrl+C) and SIGTERM (terminate signal, often sent by process managers like systemd or docker).
  3. Implement graceful shutdown: When either SIGINT or SIGTERM is received, the program should:
    • Stop the long-running process.
    • Perform any necessary cleanup (e.g., closing open connections, flushing buffers).
    • Exit cleanly with a status code of 0.
  4. Provide feedback: The program should print messages indicating when it starts, when it receives a signal, and when it is shutting down.

Examples

Example 1:

Input: (No explicit input, program runs until interrupted)
Output:
Application started. Listening for signals...
[Timestamp] Working...
[Timestamp] Working...
[Timestamp] Received SIGINT. Initiating graceful shutdown...
[Timestamp] Cleaning up resources...
[Timestamp] Application shutting down gracefully.

Explanation: The program starts, prints its initial message, and then enters its simulated work loop. When the user presses Ctrl+C, sending SIGINT, the program catches the signal, stops its work, performs cleanup, and exits.

Example 2:

Input: (Program is killed by a process manager with SIGTERM)
Output:
Application started. Listening for signals...
[Timestamp] Working...
[Timestamp] Working...
[Timestamp] Received SIGTERM. Initiating graceful shutdown...
[Timestamp] Cleaning up resources...
[Timestamp] Application shutting down gracefully.

Explanation: Similar to Example 1, but this time the signal is SIGTERM, demonstrating the program's ability to handle different termination signals.

Constraints

  • The program must run on Linux, macOS, or Windows.
  • The simulated long-running process should not consume excessive CPU or memory.
  • The shutdown process should be completed within a reasonable time (e.g., under 5 seconds for cleanup).
  • The program should not block indefinitely during shutdown.

Notes

  • Consider using context.Context for managing cancellation and signaling between goroutines.
  • The os/signal package is your primary tool for handling signals.
  • The runtime.NumGoroutine() function can be helpful for debugging and ensuring all goroutines have exited.
  • Think about how to signal your long-running goroutine to stop from the main signal handling goroutine.
Loading editor...
go