Index: src/supervisor/process.py
===================================================================
--- src/supervisor/process.py	(revision 838)
+++ src/supervisor/process.py	(working copy)
@@ -21,6 +21,7 @@
 import StringIO
 import traceback
 import signal
+import select
 
 from supervisor.states import ProcessStates
 from supervisor.states import SupervisorStates
@@ -82,15 +83,45 @@
                 dispatcher.reopenlogs()
 
     def drain(self):
-        for dispatcher in self.dispatchers.values():
-            # note that we *must* call readable() for every
-            # dispatcher, as it may have side effects for a given
-            # dispatcher (eg. call handle_listener_state_change for
-            # event listener processes)
+        r, w, x = [], [], []
+        timeout = 1
+        for fd, dispatcher in self.dispatchers.items():
             if dispatcher.readable():
-                dispatcher.handle_read_event()
+                r.append(fd)
             if dispatcher.writable():
-                dispatcher.handle_write_event()
+                w.append(fd)
+            try:
+                r, w, x = self.config.options.select(r, w, x, timeout)
+            except select.error, err:
+                r = w = x = []
+                if err[0] == errno.EINTR:
+                    self.config.options.logger.blather('EINTR encountered in select')
+                else:
+                    raise
+        for fd in r:
+            if self.dispatchers.has_key(fd):
+                try:
+                    dispatcher = self.dispatchers[fd]
+                    self.config.options.logger.blather(
+                        'read event caused by %(dispatcher)s',
+                        dispatcher=dispatcher)
+                    dispatcher.handle_read_event()
+                except asyncore.ExitNow:
+                    raise
+                except:
+                    self.dispatchers[fd].handle_error()
+        for fd in w:
+            if self.dispatchers.has_key(fd):
+                try:
+                    dispatcher = self.dispatchers[fd]
+                    self.config.options.logger.blather(
+                        'write event caused by %(dispatcher)s',
+                        dispatcher=dispatcher)
+                    dispatcher.handle_write_event()
+                except asyncore.ExitNow:
+                    raise
+                except:
+                    self.dispatchers[fd].handle_error()
                 
     def write(self, chars):
         if not self.pid or self.killing:
