Commit 8e40fb59 authored by Julien Muchembled's avatar Julien Muchembled

testnode: fix ProcessManager to not kill too many processes

parent d759fd9a
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
# #
############################################################################## ##############################################################################
import os import os
import getpass
import psutil import psutil
import re import re
import subprocess import subprocess
...@@ -102,38 +101,31 @@ def subprocess_capture(p, log, log_prefix, get_output=True): ...@@ -102,38 +101,31 @@ def subprocess_capture(p, log, log_prefix, get_output=True):
def killCommand(pid, log): def killCommand(pid, log):
""" """
To avoid letting orphaned childs, we stop the process and all it's To prevent processes from reacting to the KILL of other processes,
child (until childs does not change) and then we brutally kill we STOP them all first, and we repeat until the list of children does not
everyone at the same time change anymore. Only then, we KILL them all.
""" """
try: try:
process = psutil.Process(pid) process = psutil.Process(pid)
new_child_set = set([x.pid for x in process.children(recursive=True)]) process.suspend()
child_set = None except psutil.Error, e:
return
process_list = [process]
new_list = process.children(recursive=True)
while new_list:
process_list += new_list
for child in new_list:
try: try:
os.kill(pid, signal.SIGSTOP) child.suspend()
except OSError: except psutil.Error, e:
pass log("killCommand/suspend: %s", e)
while new_child_set != child_set:
child_set = new_child_set
log("killCommand, new_child_set : %r, child_set: %r" % (
new_child_set, child_set))
for child_pid in child_set:
try:
os.kill(child_pid, signal.SIGSTOP)
except OSError:
log("killCommand, OSError, %r is already dead" % child_pid)
pass
time.sleep(1) time.sleep(1)
child_set = new_child_set new_list = set(process.children(recursive=True)).difference(process_list)
new_child_set = set([x.pid for x in process.children(recursive=True)]) for process in process_list:
log("killCommand, finishing, child_set : %r" % (child_set,)) try:
for child_pid in child_set: process.kill()
os.kill(child_pid, signal.SIGKILL) except psutil.Error, e:
os.kill(pid, signal.SIGKILL) log("killCommand/kill: %s", e)
except psutil.NoSuchProcess:
log("killCommand, NoSuchProcess raised")
pass
class ProcessManager(object): class ProcessManager(object):
...@@ -201,18 +193,27 @@ class ProcessManager(object): ...@@ -201,18 +193,27 @@ class ProcessManager(object):
def killall(self, name): def killall(self, name):
""" """
Allow to kill process with given name. Kill processes of given name, only if they're orphan or subprocesses of
Will try to kill only process belonging to current user the testnode.
""" """
user_login = getpass.getuser()
to_kill_list = [] to_kill_list = []
pid = os.getpid()
for process in psutil.process_iter(): for process in psutil.process_iter():
try: try:
if process.username() == user_login and process.name() == name: if process.name() != name:
continue
p = process.parent()
if p is not None:
while p is not None:
if p.pid == pid:
break
p = p.parent()
else:
continue
except (psutil.AccessDenied, psutil.NoSuchProcess):
continue
self.log('ProcesssManager, killall on %s having pid %s' % (name, process.pid)) self.log('ProcesssManager, killall on %s having pid %s' % (name, process.pid))
to_kill_list.append(process.pid) to_kill_list.append(process.pid)
except psutil.NoSuchProcess:
pass
for pid in to_kill_list: for pid in to_kill_list:
killCommand(pid, self.log) killCommand(pid, self.log)
...@@ -223,10 +224,7 @@ class ProcessManager(object): ...@@ -223,10 +224,7 @@ class ProcessManager(object):
for timer in self.timer_set: for timer in self.timer_set:
timer.cancel() timer.cancel()
for pgpid in self.process_pid_set: for pgpid in self.process_pid_set:
try:
killCommand(pgpid, self.log) killCommand(pgpid, self.log)
except:
pass
try: try:
if os.path.exists(self.supervisord_pid_file): if os.path.exists(self.supervisord_pid_file):
supervisor_pid = int(open(self.supervisord_pid_file).read().strip()) supervisor_pid = int(open(self.supervisord_pid_file).read().strip())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment