Skip to content

Instantly share code, notes, and snippets.

@phizaz
Last active August 7, 2016 08:45
Show Gist options
  • Save phizaz/4ee94fd75ae00fca5bc69232f4aa5b85 to your computer and use it in GitHub Desktop.
Save phizaz/4ee94fd75ae00fca5bc69232f4aa5b85 to your computer and use it in GitHub Desktop.
Python SafeQuitProcess: On termination the process also propagates the termination signal to all its children
from multiprocessing import Process
class SafeQuitProcess(Process):
def __init__(self, target, args=[], kwargs=dict()):
super(SafeQuitProcess, self).__init__(target=target,
args=args,
kwargs=kwargs)
def terminate(self):
'''
Recursively terminates all the child processes
'''
import psutil, signal
p_process = psutil.Process(self.pid)
children = p_process.children(recursive=True)
for process in children:
process.send_signal(signal.SIGTERM)
super(SafeQuitProcess, self).terminate()
class SafeQuitProcessTest(unittest.TestCase):
def test_terminate(self):
from multiprocessing import Queue
err = Queue()
def dummy():
import time
time.sleep(1)
err.put(True)
p = SafeQuitProcess(target=dummy)
p.start()
p.terminate()
p.join()
self.assertTrue(err.empty())
def test_terminate_recursively(self):
from multiprocessing import Queue
all_processes = Queue()
def dummy():
import os
all_processes.put(os.getpid())
import time
time.sleep(0.5)
def complex_dummy():
p = Process(target=dummy)
p.start()
p.join()
def run():
import time
p = SafeQuitProcess(target=complex_dummy)
p.start()
time.sleep(0.1)
p.terminate()
p.join()
if all_processes.empty():
raise Exception('the dummy has not been spawned')
else:
dummy_pid = all_processes.get()
import os
# it should not be able to kill a non-existing process
self.assertRaises(OSError, os.kill, dummy_pid, 0)
run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment