summaryrefslogtreecommitdiffstats
path: root/third_party/android_testrunner/patch.diff
blob: 9b067cd50b28000c42dd1d6fe4bc6a02a40c7ebd (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
103
104
diff --git a/third_party/android_testrunner/run_command.py b/third_party/android_testrunner/run_command.py
index d398daa..6b84156 100644
--- a/third_party/android_testrunner/run_command.py
+++ b/third_party/android_testrunner/run_command.py
@@ -19,6 +19,7 @@
 import os
 import signal
 import subprocess
+import tempfile
 import threading
 import time
 
@@ -80,31 +81,36 @@ def RunOnce(cmd, timeout_time=None, return_output=True, stdin_input=None):
   """
   start_time = time.time()
   so = []
-  pid = []
   global _abort_on_error, error_occurred
   error_occurred = False
 
+  if return_output:
+    output_dest = tempfile.TemporaryFile(bufsize=0)
+  else:
+    # None means direct to stdout
+    output_dest = None
+  if stdin_input:
+    stdin_dest = subprocess.PIPE
+  else:
+    stdin_dest = None
+  pipe = subprocess.Popen(
+      cmd,
+      executable='/bin/bash',
+      stdin=stdin_dest,
+      stdout=output_dest,
+      stderr=subprocess.STDOUT,
+      shell=True, close_fds=True,
+      preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL))
+
   def Run():
     global error_occurred
-    if return_output:
-      output_dest = subprocess.PIPE
-    else:
-      # None means direct to stdout
-      output_dest = None
-    if stdin_input:
-      stdin_dest = subprocess.PIPE
-    else:
-      stdin_dest = None
-    pipe = subprocess.Popen(
-        cmd,
-        executable='/bin/bash',
-        stdin=stdin_dest,
-        stdout=output_dest,
-        stderr=subprocess.STDOUT,
-        shell=True)
-    pid.append(pipe.pid)
     try:
-      output = pipe.communicate(input=stdin_input)[0]
+      pipe.communicate(input=stdin_input)
+      output = None
+      if return_output:
+        output_dest.seek(0)
+        output = output_dest.read()
+        output_dest.close()
       if output is not None and len(output) > 0:
         so.append(output)
     except OSError, e:
@@ -119,27 +125,17 @@ def RunOnce(cmd, timeout_time=None, return_output=True, stdin_input=None):
 
   t = threading.Thread(target=Run)
   t.start()
-
-  break_loop = False
-  while not break_loop:
-    if not t.isAlive():
-      break_loop = True
-
-    # Check the timeout
-    if (not break_loop and timeout_time is not None
-        and time.time() > start_time + timeout_time):
-      try:
-        os.kill(pid[0], signal.SIGKILL)
-      except OSError:
-        # process already dead. No action required.
-        pass
-
+  t.join(timeout_time)
+  if t.isAlive():
+    try:
+      pipe.kill()
+    except OSError:
+      # Can't kill a dead process.
+      pass
+    finally:
       logger.SilentLog("about to raise a timeout for: %s" % cmd)
       raise errors.WaitForResponseTimedOutError
-    if not break_loop:
-      time.sleep(0.1)
 
-  t.join()
   output = "".join(so)
   if _abort_on_error and error_occurred:
     raise errors.AbortError(msg=output)