1From 8a18a6c1dea7cce6669d0eeb4230e85aa88d8e44 Mon Sep 17 00:00:00 2001 2From: Hongxu Jia <hongxu.jia@windriver.com> 3Date: Fri, 23 Nov 2018 17:03:58 +0800 4Subject: [PATCH 02/11] run_program support timeout 5 6Upstream-Status: Pending 7 8Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> 9--- 10 blivet/util.py | 70 +++++++++++++++++++++++++++++--------------------- 11 1 file changed, 41 insertions(+), 29 deletions(-) 12 13diff --git a/blivet/util.py b/blivet/util.py 14index f8a8f88..a5da7b6 100644 15--- a/blivet/util.py 16+++ b/blivet/util.py 17@@ -171,6 +171,30 @@ class Path(str): 18 def __hash__(self): 19 return self._path.__hash__() 20 21+def timeout_command(argv, timeout, *args, **kwargs): 22+ """call shell-command and either return its output or kill it 23+ if it doesn't normally exit within timeout seconds and return None""" 24+ import subprocess, datetime, os, time, signal 25+ start = datetime.datetime.now() 26+ 27+ try: 28+ proc = subprocess.Popen(argv, *args, **kwargs) 29+ while proc.poll() is None: 30+ time.sleep(0.1) 31+ now = datetime.datetime.now() 32+ if (now - start).seconds> timeout: 33+ os.kill(proc.pid, signal.SIGKILL) 34+ os.waitpid(-1, os.WNOHANG) 35+ program_log.debug("%d seconds timeout" % timeout) 36+ return (-1, None) 37+ 38+ 39+ except OSError as e: 40+ program_log.error("Error running %s: %s", argv[0], e.strerror) 41+ raise 42+ 43+ program_log.debug("Return code: %d", proc.returncode) 44+ return (proc.returncode, proc.stdout.read()) 45 46 def _run_program(argv, root='/', stdin=None, env_prune=None, stderr_to_stdout=False, binary_output=False): 47 if env_prune is None: 48@@ -193,35 +217,23 @@ def _run_program(argv, root='/', stdin=None, env_prune=None, stderr_to_stdout=Fa 49 stderr_dir = subprocess.STDOUT 50 else: 51 stderr_dir = subprocess.PIPE 52- try: 53- proc = subprocess.Popen(argv, # pylint: disable=subprocess-popen-preexec-fn 54- stdin=stdin, 55- stdout=subprocess.PIPE, 56- stderr=stderr_dir, 57- close_fds=True, 58- preexec_fn=chroot, cwd=root, env=env) 59- 60- out, err = proc.communicate() 61- if not binary_output and six.PY3: 62- out = out.decode("utf-8") 63- if out: 64- if not stderr_to_stdout: 65- program_log.info("stdout:") 66- for line in out.splitlines(): 67- program_log.info("%s", line) 68- 69- if not stderr_to_stdout and err: 70- program_log.info("stderr:") 71- for line in err.splitlines(): 72- program_log.info("%s", line) 73- 74- except OSError as e: 75- program_log.error("Error running %s: %s", argv[0], e.strerror) 76- raise 77- 78- program_log.debug("Return code: %d", proc.returncode) 79- 80- return (proc.returncode, out) 81+ 82+ res, out = timeout_command(argv, 10, 83+ stdin=stdin, 84+ stdout=subprocess.PIPE, 85+ stderr=stderr_dir, 86+ close_fds=True, 87+ preexec_fn=chroot, cwd=root, env=env) 88+ if not binary_output and six.PY3: 89+ out = out.decode("utf-8") 90+ if out: 91+ if not stderr_to_stdout: 92+ program_log.info("stdout:") 93+ for line in out.splitlines(): 94+ program_log.info("%s", line) 95+ 96+ return (res, out) 97+ 98 99 100 def run_program(*args, **kwargs): 101