![](https://secure.gravatar.com/avatar/8b97b5aad24c30e4a1357b38cc39aeaa.jpg?s=120&d=mm&r=g)
Stefan Behnel wrote:
Martijn Faassen wrote:
Attached is a small tarball that demonstrates code that crashes when the code is run in a thread but doesn't crash when it is run stand-alone. I isolated the specific XSLT + XML combination that seems to trigger this crash. I suspect it has to do with passing an XSLT object to a thread.
Ok, this is plain evil. What you do here is this:
... <tr class="odd"> <xsl:attribute name="class">top-row</xsl:attribute> ...
Note how the attribute value is changed after being set. In libxslt, this leads to a result tree update that removes the old attribute and replaces it by the new one.
Here is a minimal fix for the problem. There may be special cases where this might not work (my guess would be custom XSLT elements), but at least it works safely in this case. Stefan === src/lxml/xslt.pxi ================================================================== --- src/lxml/xslt.pxi (revision 5056) +++ src/lxml/xslt.pxi (local) @@ -486,7 +486,15 @@ _destroyFakeDoc(input_doc._c_doc, c_doc) python.PyErr_NoMemory() - initTransformDict(transform_ctxt) + # using the stylesheet dict is safer than using a possibly + # unrelated dict from the current thread. Almost all + # non-input tag/attr names will come from the stylesheet + # anyway. + if transform_ctxt.dict is not NULL: + xmlparser.xmlDictFree(transform_ctxt.dict) + transform_ctxt.dict = self._c_style.doc.dict + xmlparser.xmlDictReference(transform_ctxt.dict) + xslt.xsltSetCtxtParseOptions( transform_ctxt, input_doc._parser._parse_options)