Graceful Shutdown in Python
Many applications, especially those dealing with network connections, databases, or file operations, need to shut down cleanly. A graceful shutdown involves finishing ongoing tasks, releasing resources, and saving state before exiting, preventing data loss or corruption. This challenge asks you to implement a mechanism for gracefully shutting down a Python application, responding to signals like SIGTERM and SIGINT.
Problem Description
You are tasked with creating a Python script that gracefully handles shutdown signals (SIGTERM and SIGINT, typically triggered by Ctrl+C or a kill command). The script should simulate a long-running task (e.g., processing data, writing to a file) and ensure that this task is completed or properly stopped before the application exits.
Specifically, your script should:
- Register Signal Handlers: Implement signal handlers for
SIGTERMandSIGINT. - Simulate a Long-Running Task: Include a function that simulates a task that takes a few seconds to complete. This task should print progress updates periodically.
- Graceful Shutdown Logic: When a shutdown signal is received:
- Set a flag indicating that shutdown is in progress.
- Allow the long-running task to finish its current iteration (or a small portion of it) before exiting.
- Print a message indicating that the application is shutting down gracefully.
- Exit with a status code of 0 (success).
- Prevent Immediate Exit: The signal handler should not immediately exit the program upon receiving a signal. It should initiate the shutdown process.
- Clean Up (Optional): You can optionally include cleanup actions within the signal handler, such as closing files or releasing network connections. For this challenge, a simple print statement is sufficient.
Examples
Example 1:
Input: The script is running, simulating a task. The user presses Ctrl+C (SIGINT).
Output:
[00:00:01] Processing...
[00:00:02] Processing...
[00:00:03] Shutting down gracefully...
Explanation: The script receives SIGINT, sets the shutdown flag, allows the task to run for a few iterations, prints a shutdown message, and exits.
Example 2:
Input: The script is running, simulating a task. The user sends a SIGTERM signal (e.g., using `kill -15 <pid>`).
Output:
[00:00:01] Processing...
[00:00:02] Processing...
[00:00:03] Shutting down gracefully...
Explanation: Similar to Example 1, but triggered by SIGTERM.
Example 3: (Edge Case - Task already finished)
Input: The script is running, and the simulated task has already completed. The user presses Ctrl+C.
Output:
[00:00:00] Task completed.
[00:00:01] Shutting down gracefully...
Explanation: If the task finishes before the signal is received, the shutdown logic still executes, printing the graceful shutdown message.
Constraints
- The simulated task should take at least 2-3 seconds to complete a single iteration.
- The script should handle both
SIGTERM(signal number 15) andSIGINT(signal number 2). - The script should exit with a status code of 0 upon graceful shutdown.
- The script should not crash or raise unhandled exceptions.
Notes
- Use the
signalmodule to register signal handlers. - Consider using a global flag to indicate that shutdown is in progress. This flag can be checked within the long-running task to determine when to exit.
- The goal is to demonstrate a graceful shutdown, not an immediate exit. Allow the task to make progress before terminating.
- You don't need to implement a complex task; a simple loop with print statements is sufficient for demonstration purposes.
- Think about how to avoid race conditions if multiple threads or processes are involved (although this challenge focuses on a single process).