hgbook

changeset 79:53427f786a0f

Make run-example time out if shell seems to get stuck.
author Bryan O'Sullivan <bos@serpentine.com>
date Mon Sep 04 14:31:17 2006 -0700 (2006-09-04)
parents a893de25bc24
children ea951cfb5cd9
files en/examples/run-example
line diff
     1.1 --- a/en/examples/run-example	Mon Sep 04 14:20:05 2006 -0700
     1.2 +++ b/en/examples/run-example	Mon Sep 04 14:31:17 2006 -0700
     1.3 @@ -10,6 +10,7 @@
     1.4  import os
     1.5  import pty
     1.6  import re
     1.7 +import select
     1.8  import shutil
     1.9  import signal
    1.10  import stat
    1.11 @@ -41,9 +42,12 @@
    1.12      prompt = '__run_example_prompt__ '
    1.13      pi_re = re.compile(r'#\$\s*(name):\s*(.*)$')
    1.14      
    1.15 +    timeout = 5
    1.16 +
    1.17      def __init__(self, name, verbose):
    1.18          self.name = name
    1.19          self.verbose = verbose
    1.20 +        self.poll = select.poll()
    1.21  
    1.22      def parse(self):
    1.23          '''yield each hunk of input from the file.'''
    1.24 @@ -76,13 +80,23 @@
    1.25          else:
    1.26              return rs
    1.27              
    1.28 +    timeout = 5
    1.29 +
    1.30 +    def read(self):
    1.31 +        events = self.poll.poll(self.timeout * 1000)
    1.32 +        if not events:
    1.33 +            print >> sys.stderr, '[timed out after %d seconds]' % self.timeout
    1.34 +            os.kill(self.pid, signal.SIGHUP)
    1.35 +            return ''
    1.36 +        return os.read(self.cfd, 1024)
    1.37 +        
    1.38      def receive(self):
    1.39          out = cStringIO.StringIO()
    1.40          while True:
    1.41              try:
    1.42                  if self.verbose:
    1.43                      sys.stderr.write('< ')
    1.44 -                s = os.read(self.cfd, 1024)
    1.45 +                s = self.read()
    1.46              except OSError, err:
    1.47                  if err.errno == errno.EIO:
    1.48                      return ''
    1.49 @@ -126,8 +140,8 @@
    1.50          rcfp.close()
    1.51          sys.stdout.flush()
    1.52          sys.stderr.flush()
    1.53 -        pid, self.cfd = pty.fork()
    1.54 -        if pid == 0:
    1.55 +        self.pid, self.cfd = pty.fork()
    1.56 +        if self.pid == 0:
    1.57              cmdline = ['/usr/bin/env', 'bash', '--noediting', '--noprofile',
    1.58                         '--norc']
    1.59              try:
    1.60 @@ -136,10 +150,12 @@
    1.61                  print >> sys.stderr, '%s: %s' % (cmdline[0], err.strerror)
    1.62                  sys.stderr.flush()
    1.63                  os._exit(0)
    1.64 +        self.poll.register(self.cfd, select.POLLIN | select.POLLERR |
    1.65 +                           select.POLLHUP)
    1.66          try:
    1.67              try:
    1.68                  # eat first prompt string from shell
    1.69 -                os.read(self.cfd, 1024)
    1.70 +                self.read()
    1.71                  # setup env and prompt
    1.72                  self.sendreceive('source %s\n' % rcfile)
    1.73                  for hunk in self.parse():
    1.74 @@ -173,7 +189,7 @@
    1.75                  open(self.name + '.run', 'w')
    1.76              except:
    1.77                  print >> sys.stderr, '(killed)'
    1.78 -                os.kill(pid, signal.SIGKILL)
    1.79 +                os.kill(self.pid, signal.SIGKILL)
    1.80                  pid, rc = os.wait()
    1.81                  raise
    1.82              else:
    1.83 @@ -184,7 +200,7 @@
    1.84                      os.close(self.cfd)
    1.85                  except IOError:
    1.86                      pass
    1.87 -                os.kill(pid, signal.SIGTERM)
    1.88 +                os.kill(self.pid, signal.SIGTERM)
    1.89                  pid, rc = os.wait()
    1.90                  if rc:
    1.91                      if os.WIFEXITED(rc):