[svn] commit: r1908 - in /branches/trac185/src/bin/xfrin: tests/xfrin_test.py xfrin.py.in

BIND 10 source code commits bind10-changes at lists.isc.org
Sat May 22 06:33:21 UTC 2010


Author: jinmei
Date: Sat May 22 06:33:20 2010
New Revision: 1908

Log:
use per thread socket map for asyncore (instead of the default global map)
so that the underlying socket should be closed by the time the xfr thread
terminates at latest.
this will also avoid a possible race due to multiple threads sharing the
same global map.

Modified:
    branches/trac185/src/bin/xfrin/tests/xfrin_test.py
    branches/trac185/src/bin/xfrin/xfrin.py.in

Modified: branches/trac185/src/bin/xfrin/tests/xfrin_test.py
==============================================================================
--- branches/trac185/src/bin/xfrin/tests/xfrin_test.py (original)
+++ branches/trac185/src/bin/xfrin/tests/xfrin_test.py Sat May 22 06:33:20 2010
@@ -70,9 +70,9 @@
             MockXfrin.check_command_hook()
 
 class MockXfrinConnection(XfrinConnection):
-    def __init__(self, zone_name, rrclass, db_file, shutdown_event,
+    def __init__(self, sock_map, zone_name, rrclass, db_file, shutdown_event,
                  master_addr):
-        super().__init__(zone_name, rrclass, db_file, shutdown_event,
+        super().__init__(sock_map, zone_name, rrclass, db_file, shutdown_event,
                          master_addr)
         self.query_data = b''
         self.reply_data = b''
@@ -148,8 +148,10 @@
     def setUp(self):
         if os.path.exists(TEST_DB_FILE):
             os.remove(TEST_DB_FILE)
-        self.conn = MockXfrinConnection('example.com.', TEST_RRCLASS,
-                                        TEST_DB_FILE, threading.Event(),
+        self.sock_map = {}
+        self.conn = MockXfrinConnection(self.sock_map, 'example.com.',
+                                        TEST_RRCLASS, TEST_DB_FILE,
+                                        threading.Event(),
                                         TEST_MASTER_IPV4_ADDRINFO)
         self.axfr_after_soa = False
         self.soa_response_params = {
@@ -165,20 +167,29 @@
         if os.path.exists(TEST_DB_FILE):
             os.remove(TEST_DB_FILE)
 
+    def test_close(self):
+        # we shouldn't be using the global asyncore map.
+        self.assertEqual(len(asyncore.socket_map), 0)
+        # there should be exactly one entry in our local map
+        self.assertEqual(len(self.sock_map), 1)
+        # once closing the dispatch the map should become empty
+        self.conn.close()
+        self.assertEqual(len(self.sock_map), 0)
+
     def test_init_ip6(self):
         # This test simply creates a new XfrinConnection object with an
         # IPv6 address, tries to bind it to an IPv6 wildcard address/port
         # to confirm an AF_INET6 socket has been created.  A naive application
         # tends to assume it's IPv4 only and hardcode AF_INET.  This test
         # uncovers such a bug.
-        c = MockXfrinConnection('example.com.', TEST_RRCLASS, TEST_DB_FILE,
+        c = MockXfrinConnection({}, 'example.com.', TEST_RRCLASS, TEST_DB_FILE,
                                 threading.Event(),
                                 TEST_MASTER_IPV6_ADDRINFO)
         c.bind(('::', 0))
         c.close()
 
     def test_init_chclass(self):
-        c = XfrinConnection('example.com.', rr_class.CH(), TEST_DB_FILE,
+        c = XfrinConnection({}, 'example.com.', rr_class.CH(), TEST_DB_FILE,
                             threading.Event(), TEST_MASTER_IPV4_ADDRINFO)
         axfrmsg = c._create_query(rr_type.AXFR())
         self.assertEqual(question_iter(axfrmsg).get_question().get_class(),

Modified: branches/trac185/src/bin/xfrin/xfrin.py.in
==============================================================================
--- branches/trac185/src/bin/xfrin/xfrin.py.in (original)
+++ branches/trac185/src/bin/xfrin/xfrin.py.in Sat May 22 06:33:20 2010
@@ -65,15 +65,15 @@
 class XfrinConnection(asyncore.dispatcher):
     '''Do xfrin in this class. '''    
 
-    def __init__(self, 
-                 zone_name, rrclass, db_file, shutdown_event, master_addrinfo, 
-                 verbose = False, idle_timeout = 60): 
+    def __init__(self,
+                 sock_map, zone_name, rrclass, db_file, shutdown_event,
+                 master_addrinfo, verbose = False, idle_timeout = 60): 
         ''' idle_timeout: max idle time for read data from socket.
             db_file: specify the data source file.
             check_soa: when it's true, check soa first before sending xfr query
         '''
 
-        asyncore.dispatcher.__init__(self)
+        asyncore.dispatcher.__init__(self, map=sock_map)
         self.create_socket(master_addrinfo[0], master_addrinfo[1])
         self._zone_name = zone_name
         self._rrclass = rrclass
@@ -327,8 +327,9 @@
 def process_xfrin(xfrin_recorder, zone_name, rrclass, db_file, 
                   shutdown_event, master_addrinfo, check_soa, verbose):
     xfrin_recorder.increment(zone_name)
-    conn = XfrinConnection(zone_name, rrclass, db_file, shutdown_event, 
-                           master_addrinfo, verbose)
+    sock_map = {}
+    conn = XfrinConnection(sock_map, zone_name, rrclass, db_file,
+                           shutdown_event, master_addrinfo, verbose)
     if conn.connect_to_master():
         conn.do_xfrin(check_soa)
 




More information about the bind10-changes mailing list