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