Handle ^C better when threads are being used too
authorIan Lynagh <ian@well-typed.com>
Sat, 2 Feb 2013 19:53:46 +0000 (19:53 +0000)
committerIan Lynagh <ian@well-typed.com>
Sat, 2 Feb 2013 19:53:46 +0000 (19:53 +0000)
testsuite/driver/testlib.py
testsuite/timeout/timeout.py

index 9f1f759..54bae83 100644 (file)
@@ -1871,6 +1871,15 @@ def rawSystem(cmd_and_args):
     else:
         return os.spawnv(os.P_WAIT, cmd_and_args[0], cmd_and_args)
 
+# Note that this doesn't handle the timeout itself; it is just used for
+# commands that have timeout handling built-in.
+def rawSystemWithTimeout(cmd_and_args):
+    r = rawSystem(cmd_and_args)
+    if r == 98:
+        # The python timeout program uses 98 to signal that ^C was pressed
+        stopNow()
+    return r
+
 # cmd is a complex command in Bourne-shell syntax
 # e.g (cd . && 'c:/users/simonpj/darcs/HEAD/compiler/stage1/ghc-inplace' ...etc)
 # Hence it must ultimately be run by a Bourne shell
@@ -1890,7 +1899,7 @@ def runCmd( cmd ):
         assert config.timeout_prog!=''
 
     if config.timeout_prog != '':
-        r = rawSystem([config.timeout_prog, str(config.timeout), cmd])
+        r = rawSystemWithTimeout([config.timeout_prog, str(config.timeout), cmd])
     else:
         r = os.system(cmd)
     return r << 8
@@ -1906,13 +1915,14 @@ def runCmdFor( name, cmd, timeout_multiplier=1.0 ):
     if config.timeout_prog != '':
         if config.check_files_written:
             fn = name + ".strace"
-            r = rawSystem(["strace", "-o", fn, "-fF", "-e", "creat,open,chdir,clone,vfork",
-                           config.timeout_prog, str(timeout),
-                           cmd])
+            r = rawSystemWithTimeout(
+                    ["strace", "-o", fn, "-fF",
+                               "-e", "creat,open,chdir,clone,vfork",
+                     config.timeout_prog, str(timeout), cmd])
             addTestFilesWritten(name, fn)
             rm_no_fail(fn)
         else:
-            r = rawSystem([config.timeout_prog, str(timeout), cmd])
+            r = rawSystemWithTimeout([config.timeout_prog, str(timeout), cmd])
     else:
         r = os.system(cmd)
     return r << 8
index 76660a7..6a57ac2 100644 (file)
@@ -1,46 +1,53 @@
 #!/usr/bin/env python
 
-import errno
-import os
-import signal
-import sys
-import time
+try:
 
-secs = int(sys.argv[1])
-cmd = sys.argv[2]
+    import errno
+    import os
+    import signal
+    import sys
+    import time
 
-def killProcess(pid):
-    os.killpg(pid, signal.SIGKILL)
-    for x in range(10):
-        try:
-            time.sleep(0.3)
-            r = os.waitpid(pid, os.WNOHANG)
-            if r == (0, 0):
-                os.killpg(pid, signal.SIGKILL)
-            else:
-                return
-        except OSError, e:
-            if e.errno == errno.ECHILD:
-                return
-            else:
-                raise e
+    secs = int(sys.argv[1])
+    cmd = sys.argv[2]
 
-pid = os.fork()
-if pid == 0:
-    # child
-    os.setpgrp()
-    os.execvp('/bin/sh', ['/bin/sh', '-c', cmd])
-else:
-    # parent
-    def handler(signum, frame):
-        sys.stderr.write('Timeout happened...killing process...\n')
-        killProcess(pid)
-        sys.exit(99)
-    old = signal.signal(signal.SIGALRM, handler)
-    signal.alarm(secs)
-    (pid2, res) = os.waitpid(pid, 0)
-    if (os.WIFEXITED(res)):
-        sys.exit(os.WEXITSTATUS(res))
+    def killProcess(pid):
+        os.killpg(pid, signal.SIGKILL)
+        for x in range(10):
+            try:
+                time.sleep(0.3)
+                r = os.waitpid(pid, os.WNOHANG)
+                if r == (0, 0):
+                    os.killpg(pid, signal.SIGKILL)
+                else:
+                    return
+            except OSError, e:
+                if e.errno == errno.ECHILD:
+                    return
+                else:
+                    raise e
+
+    pid = os.fork()
+    if pid == 0:
+        # child
+        os.setpgrp()
+        os.execvp('/bin/sh', ['/bin/sh', '-c', cmd])
     else:
-        sys.exit(res)
+        # parent
+        def handler(signum, frame):
+            sys.stderr.write('Timeout happened...killing process...\n')
+            killProcess(pid)
+            sys.exit(99)
+        old = signal.signal(signal.SIGALRM, handler)
+        signal.alarm(secs)
+        (pid2, res) = os.waitpid(pid, 0)
+        if (os.WIFEXITED(res)):
+            sys.exit(os.WEXITSTATUS(res))
+        else:
+            sys.exit(res)
+
+except KeyboardInterrupt:
+    sys.exit(98)
+except:
+    raise