Python Signal Handling – Graceful Shutdown with SIGINT, SIGTERM
Introduction – Why Handle Signals in Python?
Signals are a core part of Unix-based systems. They allow the OS or other processes to notify your program about events such as:
- Ctrl+C (interrupt via
SIGINT) - Termination (
SIGTERM) - Hang-up (
SIGHUP) - Child process events (
SIGCHLD)
With Python’s built-in signal module, you can intercept and handle these events to:
- Shutdown cleanly
- Save state before exit
- Restart services automatically
- Handle timeouts or inter-process communication
In this guide, you’ll learn:
- What signals are and how they work in Python
- How to catch signals like
SIGINTandSIGTERM - How to safely clean up resources using signal handlers
- Best practices and limitations of signal handling
What Is a Signal?
A signal is a software interrupt sent to a process to notify it of an event (e.g., kill signal, interrupt signal).
In Python, you can register handlers that are executed when a signal is received.
Setting Up a Signal Handler
Basic Signal Handler Example
import signal
import sys
def handle_sigint(signum, frame):
print("Caught SIGINT (Ctrl+C). Exiting gracefully...")
sys.exit(0)
signal.signal(signal.SIGINT, handle_sigint)
while True:
pass # Keep running
Pressing Ctrl+C will now trigger the handler and exit cleanly.
Supported Signals (Common)
| Signal | Meaning |
|---|---|
SIGINT | Interrupt from keyboard (Ctrl+C) |
SIGTERM | Terminate program (graceful shutdown) |
SIGHUP | Hang-up (e.g., terminal closed) |
SIGCHLD | Child process status changed |
SIGALRM | Alarm signal |
SIGUSR1/2 | Custom user-defined signals |
Example – Handle SIGTERM
def handle_sigterm(signum, frame):
print("Caught SIGTERM. Cleaning up...")
sys.exit(0)
signal.signal(signal.SIGTERM, handle_sigterm)
Useful in Docker containers, daemonized apps, or system services.
Signal Parameters
The signal handler always accepts two arguments:
def handler(signum, frame):
print(f"Signal received: {signum}")
signum: signal number (e.g.,2for SIGINT)frame: current stack frame (useful for debugging)
Using signal.SIGALRM for Timeouts
import time
def timeout_handler(signum, frame):
raise TimeoutError("Operation timed out!")
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(3) # Set a 3-second timer
try:
time.sleep(5) # This will be interrupted
except TimeoutError as e:
print(e)
Raises a TimeoutError after 3 seconds.
📵 Limitations of Signal Handling in Python
| Limitation | Details |
|---|---|
| Works only in main thread | Handlers won’t run in background threads |
Can’t catch SIGKILL, SIGSTOP | These signals are uncatchable |
| Handlers must be fast | Avoid blocking or long-running logic |
Real-World Use Case – Graceful Shutdown
import time
running = True
def handle_exit(signum, frame):
global running
print("Shutdown signal received.")
running = False
signal.signal(signal.SIGINT, handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
print("Running... Press Ctrl+C to stop.")
while running:
time.sleep(1)
print("Clean exit complete.")
Ideal for cleanup scripts, cron jobs, long-running services.
Best Practices
| Do This | Avoid This |
|---|---|
| Register signals early in the program | Delaying signal setup after startup |
Handle SIGINT and SIGTERM together | Ignoring SIGTERM in production apps |
| Use flags (not direct exits) for long loops | Exiting mid-process in multithreaded apps |
| Keep handlers lightweight | Running heavy logic or blocking operations |
Summary – Recap & Next Steps
Python signal handling allows you to gracefully manage external interrupts and control how your application shuts down or responds to external events.
Key Takeaways:
- Use
signal.signal()to register signal handlers - Handle
SIGINT,SIGTERM, andSIGHUPfor clean shutdowns - Signals only affect the main thread
- Use
signal.alarm()to implement timeouts
Real-World Relevance:
Used in system daemons, CLI tools, Docker containers, and supervised services like Gunicorn, Celery, or custom schedulers.
FAQ – Python Signal Handling
Can Python catch Ctrl+C?
Yes. Use signal.SIGINT to handle keyboard interrupts.
Can I handle signals in threads?
No. Signal handlers only work in the main thread.
How do I stop a long-running loop using signals?
Set a global flag in the handler and check it inside the loop.
What signals can’t be handled?
SIGKILL(9)SIGSTOP(19)
These cannot be caught or ignored.
What’s the difference between SIGINT and SIGTERM?
SIGINT: Sent by keyboard (Ctrl+C)SIGTERM: Sent by system/process, often to gracefully stop a program
Share Now :
