Use Signals to Safely Stop processes
Here are some times you probably don’t want your process to stop:
- When saving data to disk or some other resource.
- When in the middle of some long running job.
- When doing something business critical.
We can add signal handlers that place your process into a state of stopping the next time it is ready.
import signal # (1)
import time
import os
should_quit = False # (2)
def main():
stop_signal = signal.SIGUSR1 # (3)
signal.signal(stop_signal, on_signal) # (4)
print(f"Starting - process id is: {os.getpid()}") # (5)
print(f"Send {stop_signal} to safely stop") # (6)
while not should_quit:
print("Doing work, please do not interrupt this.")
time.sleep(3) # (7)
print("Done with this unit of work")
print("Stopping")
def on_signal(signum, frame): # (8)
global should_quit
print("Received request to stop...doing so when it is safe.")
should_quit = True # (9)
if __name__ == "__main__":
main()
- The builtin signal module in Python. Most programming languages will provide a similar module for using signals.
- We use a global variable(
should_quit
) to keep track of when the program should stop. - We are choosing
SIGUSR1
for this example. There are many different signals, some are reserved for special purposes by your OS, programming language or shell.SIGUSR1
is set aside for programmers to define their own custom handler. - Here we are saying: when my program receives a
SIGUSR1
, I want you to call theon_signal
handler. - We print the process ID to make it easier to send the signal to the correct process.
- We print the signal to make it easier to send the correct signal. On my OS, behind the scenes
SIGUSR1
maps to10
. - This line represents some task your program is doing that you do not wish to interrupt.
- A signal handler is a regular function that takes two parameters
signum
andframe
. on_signal
simply setsshould_quit
toTrue
, the next time we check against it, the programs stops.
Here is an example run:
$ python program.py
Starting - process id is: 25716
Send 10 to safely stop
Doing work, please do not interrupt this.
Done with this unit of work
Doing work, please do not interrupt this.
Done with this unit of work
Doing work, please do not interrupt this.
Done with this unit of work
Doing work, please do not interrupt this.
We see that our process ID is 25716
and the signal is 10
. So to send our signal
we execute:
$ kill -10 25716
Received request to stop...doing so when it is safe.
Done with this unit of work
Stopping
Our processs receives the signal and calls our handler but the program resumes its work without interruption. The next time around, it sees that we requested to stop and does so.