Skip to content

Instantly share code, notes, and snippets.

@ivelin
Last active May 19, 2023 11:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ivelin/6a14002b623ec8b53e9987a952ff95cc to your computer and use it in GitHub Desktop.
Save ivelin/6a14002b623ec8b53e9987a952ff95cc to your computer and use it in GitHub Desktop.
Python good process kill
def _process_kill(pid, signal=0):
"""Send a signal to a process.
:Returns:
----------
True if the pid is dead
with no signal argument, sends no signal.
"""
# if 'ps --no-headers' returns no lines, the pid is dead
from os import kill
try:
return kill(pid, signal)
except OSError as e:
# process is dead
if e.errno == 3:
return True
# no permissions
elif e.errno == 1:
return False
else:
raise e
def _process_dead(pid):
if _process_kill(pid):
return True
# maybe the pid is a zombie that needs us to wait4 it
from os import waitpid, WNOHANG
try:
dead = waitpid(pid, WNOHANG)[0]
except OSError as e:
# pid is not a child
if e.errno == 10:
log.warning("Process PID %s not a child. Can't kill it." % pid)
return False
else:
raise e
return dead
# def kill(pid, sig=0): pass #DEBUG: test hang condition
def process_goodkill(pid, interval=1, hung=20):
"""Let process die gracefully.
Gradually send harsher signals
if necessary.
:Returns:
---------
True if the process was killed and exited cleanly.
False if the process kill hung up and couldn't be cleaned.
"""
from signal import SIGTERM, SIGINT, SIGHUP, SIGKILL
from time import sleep
for signal in [SIGTERM, SIGINT, SIGHUP]:
if _process_kill(pid, signal):
return
if _process_dead(pid):
return
sleep(interval)
i = 0
while True:
# infinite-loop protection
if i < hung:
i += 1
else:
log.warning("Process PID %s is hung. Giving up kill." % pid)
return
if _process_kill(pid, SIGKILL):
return
if _process_dead(pid):
return
sleep(interval)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment