[Lxml-checkins] r39231 - in lxml/trunk: . src/lxml

scoder at codespeak.net scoder at codespeak.net
Tue Feb 20 14:02:30 CET 2007


Author: scoder
Date: Tue Feb 20 14:02:27 2007
New Revision: 39231

Modified:
   lxml/trunk/CHANGES.txt
   lxml/trunk/src/lxml/etree.pyx
Log:
synchronise access to _elementFactory to prevent race conditions during upcalls to the Python interpreter

Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt	(original)
+++ lxml/trunk/CHANGES.txt	Tue Feb 20 14:02:27 2007
@@ -29,6 +29,8 @@
 Bugs fixed
 ----------
 
+* Element instantiation now uses locks to prevent race conditions with threads
+
 * ElementTree.write() did not raise an exception when the file was not writable
 
 * Error handling could crash under Python <= 2.4.1 - fixed by disabling thread

Modified: lxml/trunk/src/lxml/etree.pyx
==============================================================================
--- lxml/trunk/src/lxml/etree.pyx	(original)
+++ lxml/trunk/src/lxml/etree.pyx	Tue Feb 20 14:02:27 2007
@@ -969,19 +969,41 @@
         evaluator = XPathElementEvaluator(self, namespaces, extensions)
         return evaluator.evaluate(_path, **_variables)
 
+
+cdef python.PyThread_type_lock ELEMENT_CREATION_LOCK
+if config.ENABLE_THREADING:
+    ELEMENT_CREATION_LOCK = python.PyThread_allocate_lock()
+else:
+    ELEMENT_CREATION_LOCK = NULL
+
 cdef _Element _elementFactory(_Document doc, xmlNode* c_node):
+    cdef python.PyThreadState* state
     cdef _Element result
     result = getProxy(c_node)
     if result is not None:
         return result
     if c_node is NULL:
         return None
+
+    if config.ENABLE_THREADING:
+        state = python.PyEval_SaveThread()
+        python.PyThread_acquire_lock(ELEMENT_CREATION_LOCK, python.WAIT_LOCK)
+        python.PyEval_RestoreThread(state)
+        result = getProxy(c_node)
+        if result is not None:
+            python.PyThread_release_lock(ELEMENT_CREATION_LOCK)
+            return result
+
     element_class = LOOKUP_ELEMENT_CLASS(ELEMENT_CLASS_LOOKUP_STATE,
                                          doc, c_node)
     result = element_class()
     result._doc = doc
     result._c_node = c_node
     registerProxy(result)
+
+    if config.ENABLE_THREADING:
+        python.PyThread_release_lock(ELEMENT_CREATION_LOCK)
+
     result._init()
     return result
 


More information about the lxml-checkins mailing list