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