From 713cf821ebe17f9e1771502a85e0905ea04dafae Mon Sep 17 00:00:00 2001 From: Hongxu Jia Date: Fri, 23 Nov 2018 17:03:58 +0800 Subject: [PATCH 02/11] run_program support timeout Upstream-Status: Pending Signed-off-by: Hongxu Jia --- blivet/util.py | 70 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/blivet/util.py b/blivet/util.py index 4eac8b9..4f05076 100644 --- a/blivet/util.py +++ b/blivet/util.py @@ -158,6 +158,30 @@ class Path(str): def __hash__(self): return self._path.__hash__() +def timeout_command(argv, timeout, *args, **kwargs): + """call shell-command and either return its output or kill it + if it doesn't normally exit within timeout seconds and return None""" + import subprocess, datetime, os, time, signal + start = datetime.datetime.now() + + try: + proc = subprocess.Popen(argv, *args, **kwargs) + while proc.poll() is None: + time.sleep(0.1) + now = datetime.datetime.now() + if (now - start).seconds> timeout: + os.kill(proc.pid, signal.SIGKILL) + os.waitpid(-1, os.WNOHANG) + program_log.debug("%d seconds timeout" % timeout) + return (-1, None) + + + except OSError as e: + program_log.error("Error running %s: %s", argv[0], e.strerror) + raise + + program_log.debug("Return code: %d", proc.returncode) + return (proc.returncode, proc.stdout.read()) def _run_program(argv, root='/', stdin=None, env_prune=None, stderr_to_stdout=False, binary_output=False): if env_prune is None: @@ -180,35 +204,23 @@ def _run_program(argv, root='/', stdin=None, env_prune=None, stderr_to_stdout=Fa stderr_dir = subprocess.STDOUT else: stderr_dir = subprocess.PIPE - try: - proc = subprocess.Popen(argv, # pylint: disable=subprocess-popen-preexec-fn - stdin=stdin, - stdout=subprocess.PIPE, - stderr=stderr_dir, - close_fds=True, - preexec_fn=chroot, cwd=root, env=env) - - out, err = proc.communicate() - if not binary_output and six.PY3: - out = out.decode("utf-8") - if out: - if not stderr_to_stdout: - program_log.info("stdout:") - for line in out.splitlines(): - program_log.info("%s", line) - - if not stderr_to_stdout and err: - program_log.info("stderr:") - for line in err.splitlines(): - program_log.info("%s", line) - - except OSError as e: - program_log.error("Error running %s: %s", argv[0], e.strerror) - raise - - program_log.debug("Return code: %d", proc.returncode) - - return (proc.returncode, out) + + res, out = timeout_command(argv, 10, + stdin=stdin, + stdout=subprocess.PIPE, + stderr=stderr_dir, + close_fds=True, + preexec_fn=chroot, cwd=root, env=env) + if not binary_output and six.PY3: + out = out.decode("utf-8") + if out: + if not stderr_to_stdout: + program_log.info("stdout:") + for line in out.splitlines(): + program_log.info("%s", line) + + return (res, out) + def run_program(*args, **kwargs): -- 2.7.4