Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame^] | 1 | From 596979ed58109141a7fee680ab95b27296c022b1 Mon Sep 17 00:00:00 2001 |
Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 2 | From: Hongxu Jia <hongxu.jia@windriver.com> |
| 3 | Date: Mon, 8 May 2017 14:39:56 +0800 |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame^] | 4 | Subject: [PATCH 02/11] run_program support timeout |
Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 5 | |
| 6 | Upstream-Status: Pending |
| 7 | |
| 8 | Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> |
| 9 | --- |
| 10 | blivet/util.py | 68 +++++++++++++++++++++++++++++++++------------------------- |
| 11 | 1 file changed, 39 insertions(+), 29 deletions(-) |
| 12 | |
| 13 | diff --git a/blivet/util.py b/blivet/util.py |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame^] | 14 | index 0f2a995..05a253c 100644 |
Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 15 | --- a/blivet/util.py |
| 16 | +++ b/blivet/util.py |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame^] | 17 | @@ -157,6 +157,30 @@ class Path(str): |
Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 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: |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame^] | 48 | @@ -179,36 +203,22 @@ def _run_program(argv, root='/', stdin=None, env_prune=None, stderr_to_stdout=Fa |
Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 49 | stderr_dir = subprocess.STDOUT |
| 50 | else: |
| 51 | stderr_dir = subprocess.PIPE |
| 52 | - try: |
| 53 | - proc = subprocess.Popen(argv, |
| 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 | def run_program(*args, **kwargs): |
| 99 | return _run_program(*args, **kwargs)[0] |
| 100 | -- |
| 101 | 2.7.4 |
| 102 | |