If you want to use the subprocess approach you should make sure that all processes are killed cleanly.
import subprocess
import shlex
import sys
import signal
import psutil
def kill_child_processes(parent_pid, sig=signal.SIGTERM):
try:
parent = psutil.Process(parent_pid)
print(parent)
except psutil.NoSuchProcess:
print("parent process not existing")
return
children = parent.children(recursive=True)
print(children)
for process in children:
print("try to kill child: " + str(process))
process.send_signal(sig)
class Roscore(object):
"""
roscore wrapped into a subprocess.
Singleton implementation prevents from creating more than one instance.
"""
__initialized = False
def __init__(self):
if Roscore.__initialized:
raise Exception("You can't create more than 1 instance of Roscore.")
Roscore.__initialized = True
def run(self):
try:
self.roscore_process = subprocess.Popen(['roscore'])
self.roscore_pid = self.roscore_process.pid # pid of the roscore process (which has child processes)
except OSError as e:
sys.stderr.write('roscore could not be run')
raise e
def terminate(self):
print("try to kill child pids of roscore pid: " + str(self.roscore_pid))
kill_child_processes(self.roscore_pid)
self.roscore_process.terminate()
self.roscore_process.wait() # important to prevent from zombie process
Roscore.__initialized = False
Usage is like follows:
roscore = Roscore()
roscore.run()
roscore.terminate()
Originally posted by thinwybk with karma: 468 on 2018-05-28
This answer was NOT ACCEPTED on the original site
Post score: 3
Original comments
Comment by archiparchi on 2022-03-23:
Thank you @thinwybk !
I got to learn a lot from this piece of code. This seems like a very good practice. Here is my upvote :)