Quellcode durchsuchen

[Scripts/regression] Improve subprocess handling

This fixes two problems with subprocess handling:
 1. Use subprocess.communicate to avoid that the pipe can fill up.
 2. Use a process group to ensure that we also kill the subprocess'
    children in case of a timeout.

Note: This does not cover the case that the child returns successfully
but leaves other child processes running. AFAICS this is not easy since
subprocess.communicate() wait(2)s for the process so the pid is no
longer guaranteed to be valid to kill. So we leave this to the outside
environment (Jenkins or whatever).
Simon Gaiser vor 5 Jahren
Ursprung
Commit
c482288936
1 geänderte Dateien mit 10 neuen und 20 gelöschten Zeilen
  1. 10 20
      Scripts/regression.py

+ 10 - 20
Scripts/regression.py

@@ -1,4 +1,4 @@
-import sys, os, subprocess, re, time
+import sys, os, subprocess, re, time, signal
 
 class Result:
     def __init__(self, out, log, code):
@@ -48,29 +48,19 @@ class Regression:
                 if self.prepare:
                     self.prepare(args)
 
-                time.sleep(0.1)
-
                 p = subprocess.Popen(args,
                                      stdout=subprocess.PIPE,
-                                     stderr=subprocess.PIPE)
-
-                sleep_time = 0
-                finish = False
-                while sleep_time < self.timeout:
-                    time.sleep(0.001)
-                    if p.poll() is not None:
-                        finish = True
-                        break
-                    sleep_time += 1
-
-                if not finish and p.poll() is None:
+                                     stderr=subprocess.PIPE,
+                                     preexec_fn=os.setpgrp)
+                try:
+                    out, log = p.communicate(timeout=self.timeout * 0.001)
+                except subprocess.TimeoutExpired:
                     timed_out = True
-                    p.kill()
-
-                time.sleep(0.1)
+                    os.killpg(p.pid, signal.SIGKILL)
+                    out, log = p.communicate()
 
-                out = p.stdout.read().decode('utf-8')
-                log = p.stderr.read().decode('utf-8')
+                out = out.decode('utf-8')
+                log = log.decode('utf-8')
 
                 outputs.append(Result(out, log, p.returncode))