[Checkins] SVN: zc.ngi/branches/jim-thready/src/zc/ngi/async.py Port a trigger-related fd leak fix.

Jim Fulton jim at zope.com
Sat Oct 3 15:36:24 EDT 2009


Log message for revision 104765:
  Port a trigger-related fd leak fix.
  
  Fix global use of notify_select.
  

Changed:
  U   zc.ngi/branches/jim-thready/src/zc/ngi/async.py

-=-
Modified: zc.ngi/branches/jim-thready/src/zc/ngi/async.py
===================================================================
--- zc.ngi/branches/jim-thready/src/zc/ngi/async.py	2009-10-03 19:36:21 UTC (rev 104764)
+++ zc.ngi/branches/jim-thready/src/zc/ngi/async.py	2009-10-03 19:36:23 UTC (rev 104765)
@@ -23,6 +23,7 @@
 import socket
 import sys
 import threading
+import traceback
 
 import zc.ngi
 
@@ -100,9 +101,19 @@
             try:
                 asyncore.poll(timeout, map)
             except:
-                logger.exception('loop error')
+                traceback.print_exception(*sys.exc_info())
+                #logger.exception('loop error')
                 raise
 
+    def cleanup_map(self):
+        for c in self._map.values():
+            if isinstance(c, _Trigger):
+                continue
+            try:
+                del self._map[c.fileno()]
+            except KeyError:
+                pass
+            c.close()
 
 class dispatcher(asyncore.dispatcher):
 
@@ -172,14 +183,14 @@
             self.logger.debug('write %r', data)
         assert isinstance(data, str) or (data is zc.ngi.END_OF_DATA)
         self.__output.append(data)
-        notify_select()
+        self.implementation.notify_select()
 
     def writelines(self, data):
         if __debug__:
             self.logger.debug('writelines %r', data)
         assert not isinstance(data, str), "writelines does not accept strings"
         self.__output.append(iter(data))
-        notify_select()
+        self.implementation.notify_select()
 
     def close(self):
         self.__connected = False
@@ -187,7 +198,7 @@
         dispatcher.close(self)
         if self.control is not None:
             self.control.closed(self)
-        notify_select()
+        self.implementation.notify_select()
 
     def readable(self):
         return self.__handler is not None
@@ -293,7 +304,6 @@
     def handle_expt(self):
         self.handle_close('socket error')
 
-
 class _Connector(dispatcher):
 
     logger = logging.getLogger('zc.ngi.async.client')
@@ -403,7 +413,8 @@
 
     def handle_error(self):
         reason = sys.exc_info()[1]
-        self.logger.exception('listener error')
+        #self.logger.exception('listener error')
+        traceback.print_exception(*sys.exc_info())
         self.close()
 
 class _Listener(BaseListener):
@@ -431,7 +442,7 @@
             self.close()
             raise
         self.add_channel(map)
-        notify_select()
+        self.implementation.notify_select()
 
     def handle_accept(self):
         if not self.accepting:
@@ -445,7 +456,8 @@
                 # didn't get anything. Hm. Ignore.
                 return
         except socket.error, msg:
-            self.logger.exception("accepted failed: %s", msg)
+            traceback.print_exception(*sys.exc_info())
+            #self.logger.exception("accepted failed: %s", msg)
             return
         if __debug__:
             self.logger.debug('incoming connection %r', addr)
@@ -504,7 +516,7 @@
             self.close()
             raise
         self.add_channel(map)
-        notify_select()
+        self.implementation.notify_select()
 
     def handle_read(self):
         message, addr = self.recvfrom(self.__buffer_size)
@@ -556,13 +568,15 @@
     class _Trigger(_Triggerbase, asyncore.file_dispatcher):
         def __init__(self, map):
             _Triggerbase.__init__(self)
-            self.__readfd, self.__writefd = os.pipe()
-            asyncore.file_dispatcher.__init__(self, self.__readfd, map)
+            r, self.__writefd = os.pipe()
+            asyncore.file_dispatcher.__init__(self, r, map)
 
+            # file_dispatcher dups r, so we don't need it any more
+            os.close(r)
+
         def close(self):
-            self.del_channel(self._map)
             os.close(self.__writefd)
-            os.close(self.__readfd)
+            asyncore.file_dispatcher.close(self)
 
         def pull_trigger(self):
             if __debug__:
@@ -653,8 +667,8 @@
 call_from_thread = _select_implementation.call_from_thread
 connect = connector = _select_implementation.connect
 listener = _select_implementation.listener
-notify_select = _select_implementation.notify_select
 start_thread = _select_implementation.start_thread
 udp = _select_implementation.udp
 udp_listener = _select_implementation.udp_listener
 _map = _select_implementation._map
+cleanup_map = _select_implementation.cleanup_map



More information about the checkins mailing list