From 455071d51a47405e334a539f193326b3555c1f6d Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Sun, 27 Nov 2022 19:13:32 +0000 Subject: [PATCH] Extract kill_process to own module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is mostly to make things a bit more separate since there’s a circular dependency, which is not great. Signed-off-by: Stefan Marr --- rebench/denoise.py | 3 +- rebench/subprocess_kill.py | 69 ++++++++++++++++++++++++++++++ rebench/subprocess_with_timeout.py | 59 +------------------------ 3 files changed, 73 insertions(+), 58 deletions(-) create mode 100644 rebench/subprocess_kill.py diff --git a/rebench/denoise.py b/rebench/denoise.py index e86e52c3..ba98b38e 100644 --- a/rebench/denoise.py +++ b/rebench/denoise.py @@ -12,7 +12,8 @@ from cpuinfo import get_cpu_info from .ui import escape_braces -from .subprocess_with_timeout import output_as_str, kill_process +from .subprocess_with_timeout import output_as_str +from .subprocess_kill import kill_process try: from . import __version__ as rebench_version diff --git a/rebench/subprocess_kill.py b/rebench/subprocess_kill.py new file mode 100644 index 00000000..99b18331 --- /dev/null +++ b/rebench/subprocess_kill.py @@ -0,0 +1,69 @@ +from os import kill +from signal import SIGKILL +from subprocess import PIPE, Popen + +IS_PY3 = None + +try: + _ = ProcessLookupError + IS_PY3 = True +except NameError: + IS_PY3 = False + +# Indicate timeout with standard exit code +E_TIMEOUT = -9 + + +def _kill_py2(proc_id, uses_sudo): + if uses_sudo: + from .denoise import deliver_kill_signal + + deliver_kill_signal(proc_id) + return + + try: + kill(proc_id, SIGKILL) + except IOError: + # it's a race condition, so let's simply ignore it + pass + + +def _kill_py3(proc_id, uses_sudo): + if uses_sudo: + from .denoise import deliver_kill_signal + + deliver_kill_signal(proc_id) + return + + try: + kill(proc_id, SIGKILL) + except ProcessLookupError: # pylint: disable=undefined-variable + # it's a race condition, so let's simply ignore it + pass + + +def kill_process(pid, recursively, thread, uses_sudo): + pids = [pid] + if recursively: + pids.extend(_get_process_children(pid)) + + for proc_id in pids: + if IS_PY3: + _kill_py3(proc_id, uses_sudo) + else: + _kill_py2(proc_id, uses_sudo) + + if thread: + thread.join() + return E_TIMEOUT, thread.stdout_result, thread.stderr_result + return E_TIMEOUT, None, None + + +def _get_process_children(pid): + # pylint: disable-next=consider-using-with + proc = Popen('pgrep -P %d' % pid, shell=True, stdout=PIPE, stderr=PIPE) + stdout, _stderr = proc.communicate() + result = [int(p) for p in stdout.split()] + for child in result[:]: + result.extend(_get_process_children(child)) + return result diff --git a/rebench/subprocess_with_timeout.py b/rebench/subprocess_with_timeout.py index 45021930..585783cc 100644 --- a/rebench/subprocess_with_timeout.py +++ b/rebench/subprocess_with_timeout.py @@ -1,14 +1,14 @@ from __future__ import print_function -from os import kill from select import select -from signal import SIGKILL from subprocess import PIPE, STDOUT, Popen from threading import Thread, Condition from time import time import sys +from .subprocess_kill import kill_process + IS_PY3 = None try: @@ -165,58 +165,3 @@ def run(args, env, cwd=None, shell=False, kill_tree=True, timeout=-1, raise exp # pylint: disable=raising-bad-type return thread.returncode, thread.stdout_result, thread.stderr_result - - -def _kill_py2(proc_id, uses_sudo): - if uses_sudo: - from .denoise import deliver_kill_signal - - deliver_kill_signal(proc_id) - return - - try: - kill(proc_id, SIGKILL) - except IOError: - # it's a race condition, so let's simply ignore it - pass - - -def _kill_py3(proc_id, uses_sudo): - if uses_sudo: - from .denoise import deliver_kill_signal - - deliver_kill_signal(proc_id) - return - - try: - kill(proc_id, SIGKILL) - except ProcessLookupError: # pylint: disable=undefined-variable - # it's a race condition, so let's simply ignore it - pass - - -def kill_process(pid, recursively, thread, uses_sudo): - pids = [pid] - if recursively: - pids.extend(_get_process_children(pid)) - - for proc_id in pids: - if IS_PY3: - _kill_py3(proc_id, uses_sudo) - else: - _kill_py2(proc_id, uses_sudo) - - if thread: - thread.join() - return E_TIMEOUT, thread.stdout_result, thread.stderr_result - return E_TIMEOUT, None, None - - -def _get_process_children(pid): - # pylint: disable-next=consider-using-with - proc = Popen('pgrep -P %d' % pid, shell=True, stdout=PIPE, stderr=PIPE) - stdout, _stderr = proc.communicate() - result = [int(p) for p in stdout.split()] - for child in result[:]: - result.extend(_get_process_children(child)) - return result