aboutsummaryrefslogtreecommitdiffstats
path: root/meta-python/recipes-extended/python-blivet/python3-blivet/0002-run_program-support-timeout.patch
blob: fea225407434c0ec35431667f9cb4f6f2216a277 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
From 596979ed58109141a7fee680ab95b27296c022b1 Mon Sep 17 00:00:00 2001
From: Hongxu Jia <hongxu.jia@windriver.com>
Date: Mon, 8 May 2017 14:39:56 +0800
Subject: [PATCH 02/11] run_program support timeout

Upstream-Status: Pending

Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
---
 blivet/util.py | 68 +++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 39 insertions(+), 29 deletions(-)

diff --git a/blivet/util.py b/blivet/util.py
index 0f2a995..05a253c 100644
--- a/blivet/util.py
+++ b/blivet/util.py
@@ -157,6 +157,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:
@@ -179,36 +203,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