From 86744d408b91acdcb086a03d7779fcda152f2ac3 Mon Sep 17 00:00:00 2001 From: Hongxu Jia Date: Mon, 8 May 2017 14:39:56 +0800 Subject: [PATCH 02/13] run_program support timeout Upstream-Status: Pending Signed-off-by: Hongxu Jia --- blivet/util.py | 68 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/blivet/util.py b/blivet/util.py index 0cf5188..d4bd9bb 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,36 +204,22 @@ 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, - 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): return _run_program(*args, **kwargs)[0] -- 2.7.4