
Hi, 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. In your case, the stylesheet that was parsed outside the thread inherits the name dict from the main thread, while the input document inherits the one from the worker thread that executes this function: def render(id, xml, stylesheet): doc = etree.parse(StringIO(xml)) result_tree = stylesheet(doc) So the first "class" attribute name comes from the stylesheet dict and gets stored in the result document that inherits the thread dict of the input document. When it is overwritten and deleted, it is looked up in the thread dict, is not found there, and thus free()-ed, although it continues to 'live' in the stylesheet dict. This must really be the only place in XSLT where the result document is not only created incrementally but where its existing content gets overwritten. For now, I really do not know how to work around this. There can only be one dict for the result document, but the original attribute can come from the stylesheet or the input document (or even the current thread dict where the XSLT is executed), and the dict lookup happens from deep inside libxslt. I'm very open to ideas. Stefan