Use signals instead of sleep to wait for jobs
diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py
index df83b30..39670f1 100755
--- a/tools/run_tests/jobset.py
+++ b/tools/run_tests/jobset.py
@@ -33,6 +33,7 @@
 import multiprocessing
 import os
 import random
+import signal
 import subprocess
 import sys
 import tempfile
@@ -42,6 +43,12 @@
 _DEFAULT_MAX_JOBS = 16 * multiprocessing.cpu_count()
 
 
+# setup a signal handler so that signal.pause registers 'something'
+# when a child finishes
+# not using futures and threading to avoid a dependency on subprocess32
+signal.signal(signal.SIGCHLD, lambda unused_signum, unused_frame: None)
+
+
 def shuffle_iteratable(it):
   """Return an iterable that randomly walks it"""
   # take a random sampling from the passed in iterable
@@ -232,7 +239,7 @@
       if dead: return
       message('WAITING', '%d jobs running, %d complete, %d failed' % (
           len(self._running), self._completed, self._failures))
-      time.sleep(0.1)
+      signal.pause()
 
   def cancelled(self):
     """Poll for cancellation."""