[xml] side effects of thread-enabling libxml2



I'm fearing side effect with libxml2 now defaulting to with-threads=yes.
The problem lies with per-thread globals, and the per-thread generic error
handler in particular.

Currently, I use libxml2 from the python bindings in a multithreaded
environment. Even when libxml2 is not thread aware, this is safe
(if not particularly thread friendly), since libxm2 calls are protected
by the python global interpreter lock.

Now, if my sysadmin deploys libxml2 2.5.7 (with-threads=yes),
the behaviour of my programs will suddenly change, because
the python bindings set a single generic error handler wrapper
at initialization time, and not for each thread that is created.

The attached test case illustrates the problem: the error handler
set in each thread is not taken into account if libxml2 is compiled
with-threads=yes.

I have several questions:
0. Do other applications risk the same problem?
1. should I  attempt to change the python bindings so the globals in
there are also created per-threads (not a pleasant perspective).
2. if libxml2 does that, should libxslt do the same thing?
3. would it possible to build libxml2 so that applications that are not
thread-aware are not affected by the fact that libxml2 is or is not
thread-aware?

-sbi

import string
import libxml2

from threading import Thread

failed = 0

class ErrorHandler:

    def __init__(self):
        self.errors = []

    def handler(self,ctx,str):
        self.errors.append(str)

def test():
    eh = ErrorHandler()
    libxml2.registerErrorHandler(eh.handler,"")
    try:
        doc = libxml2.parseFile("bad.xml")
    except:
        if len(eh.errors):
            print "OK:",string.join(eh.errors)
        else:
            failed = 1
            print "FAILED"


test()
ts = []
for i in range(2):
    ts.append(Thread(target=test))
for t in ts:
    t.start()
for t in ts:
    t.join()

if failed:
    print "FAILED"
    sys.exit(1)

# Memory debug specific
libxml2.cleanupParser()
if libxml2.debugMemory(1) == 0:
    print "OK"
else:
    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
    libxml2.dumpMemory()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]