changeset 79:53427f786a0f

Make run-example time out if shell seems to get stuck.
author Bryan O'Sullivan <bos@serpentine.com>
date Mon, 04 Sep 2006 14:31:17 -0700
parents a893de25bc24
children ea951cfb5cd9
files en/examples/run-example
diffstat 1 files changed, 22 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/en/examples/run-example	Mon Sep 04 14:20:05 2006 -0700
+++ b/en/examples/run-example	Mon Sep 04 14:31:17 2006 -0700
@@ -10,6 +10,7 @@
 import os
 import pty
 import re
+import select
 import shutil
 import signal
 import stat
@@ -41,9 +42,12 @@
     prompt = '__run_example_prompt__ '
     pi_re = re.compile(r'#\$\s*(name):\s*(.*)$')
     
+    timeout = 5
+
     def __init__(self, name, verbose):
         self.name = name
         self.verbose = verbose
+        self.poll = select.poll()
 
     def parse(self):
         '''yield each hunk of input from the file.'''
@@ -76,13 +80,23 @@
         else:
             return rs
             
+    timeout = 5
+
+    def read(self):
+        events = self.poll.poll(self.timeout * 1000)
+        if not events:
+            print >> sys.stderr, '[timed out after %d seconds]' % self.timeout
+            os.kill(self.pid, signal.SIGHUP)
+            return ''
+        return os.read(self.cfd, 1024)
+        
     def receive(self):
         out = cStringIO.StringIO()
         while True:
             try:
                 if self.verbose:
                     sys.stderr.write('< ')
-                s = os.read(self.cfd, 1024)
+                s = self.read()
             except OSError, err:
                 if err.errno == errno.EIO:
                     return ''
@@ -126,8 +140,8 @@
         rcfp.close()
         sys.stdout.flush()
         sys.stderr.flush()
-        pid, self.cfd = pty.fork()
-        if pid == 0:
+        self.pid, self.cfd = pty.fork()
+        if self.pid == 0:
             cmdline = ['/usr/bin/env', 'bash', '--noediting', '--noprofile',
                        '--norc']
             try:
@@ -136,10 +150,12 @@
                 print >> sys.stderr, '%s: %s' % (cmdline[0], err.strerror)
                 sys.stderr.flush()
                 os._exit(0)
+        self.poll.register(self.cfd, select.POLLIN | select.POLLERR |
+                           select.POLLHUP)
         try:
             try:
                 # eat first prompt string from shell
-                os.read(self.cfd, 1024)
+                self.read()
                 # setup env and prompt
                 self.sendreceive('source %s\n' % rcfile)
                 for hunk in self.parse():
@@ -173,7 +189,7 @@
                 open(self.name + '.run', 'w')
             except:
                 print >> sys.stderr, '(killed)'
-                os.kill(pid, signal.SIGKILL)
+                os.kill(self.pid, signal.SIGKILL)
                 pid, rc = os.wait()
                 raise
             else:
@@ -184,7 +200,7 @@
                     os.close(self.cfd)
                 except IOError:
                     pass
-                os.kill(pid, signal.SIGTERM)
+                os.kill(self.pid, signal.SIGTERM)
                 pid, rc = os.wait()
                 if rc:
                     if os.WIFEXITED(rc):