mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-23 01:52:48 +03:00
On Windows, malloc hooks can be called after the final call to xmlCleanupParser in various tests. This means that xmlMemMutex can still be accessed if memory debugging is enabled, so the mutex should not be cleaned. This also means that tests may report spurious memory leaks on Windows. The old implementation avoided the issue by keeping track of all global state objects in a doubly linked list, so they could be cleaned during xmlCleanupParser. But as far as I can tell all memory will be freed eventually, so this is mostly an issue with our test suite.
106 lines
2.5 KiB
Python
Executable File
106 lines
2.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import string, sys, time
|
|
try:
|
|
from _thread import get_ident
|
|
except:
|
|
from thread import get_ident
|
|
from threading import Thread, Lock
|
|
|
|
import setup_test
|
|
import libxml2
|
|
|
|
# Memory debug specific
|
|
libxml2.debugMemory(1)
|
|
|
|
THREADS_COUNT = 15
|
|
|
|
failed = 0
|
|
|
|
class ErrorHandler:
|
|
|
|
def __init__(self):
|
|
self.errors = []
|
|
self.lock = Lock()
|
|
|
|
def handler(self,ctx,str):
|
|
self.lock.acquire()
|
|
self.errors.append(str)
|
|
self.lock.release()
|
|
|
|
def getLineNumbersDefault():
|
|
old = libxml2.lineNumbersDefault(0)
|
|
libxml2.lineNumbersDefault(old)
|
|
return old
|
|
|
|
def test(expectedLineNumbersDefault):
|
|
time.sleep(1)
|
|
global failed
|
|
# check a per thread-global
|
|
if expectedLineNumbersDefault != getLineNumbersDefault():
|
|
failed = 1
|
|
print("FAILED to obtain correct value for " \
|
|
"lineNumbersDefault in thread %d" % get_ident())
|
|
# check ther global error handler
|
|
# (which is NOT per-thread in the python bindings)
|
|
try:
|
|
doc = libxml2.parseFile("bad.xml")
|
|
except:
|
|
pass
|
|
else:
|
|
assert "failed"
|
|
|
|
# global error handler
|
|
eh = ErrorHandler()
|
|
libxml2.registerErrorHandler(eh.handler,"")
|
|
|
|
# set on the main thread only
|
|
libxml2.lineNumbersDefault(1)
|
|
test(1)
|
|
ec = len(eh.errors)
|
|
if ec == 0:
|
|
print("FAILED: should have obtained errors")
|
|
sys.exit(1)
|
|
|
|
ts = []
|
|
for i in range(THREADS_COUNT):
|
|
# expect 0 for lineNumbersDefault because
|
|
# the new value has been set on the main thread only
|
|
ts.append(Thread(target=test,args=(0,)))
|
|
for t in ts:
|
|
t.start()
|
|
for t in ts:
|
|
t.join()
|
|
|
|
if len(eh.errors) != ec+THREADS_COUNT*ec:
|
|
print("FAILED: did not obtain the correct number of errors")
|
|
sys.exit(1)
|
|
|
|
# set lineNumbersDefault for future new threads
|
|
libxml2.thrDefLineNumbersDefaultValue(1)
|
|
ts = []
|
|
for i in range(THREADS_COUNT):
|
|
# expect 1 for lineNumbersDefault
|
|
ts.append(Thread(target=test,args=(1,)))
|
|
for t in ts:
|
|
t.start()
|
|
for t in ts:
|
|
t.join()
|
|
|
|
if len(eh.errors) != ec+THREADS_COUNT*ec*2:
|
|
print("FAILED: did not obtain the correct number of errors")
|
|
sys.exit(1)
|
|
|
|
if failed:
|
|
print("FAILED")
|
|
sys.exit(1)
|
|
|
|
# Memory debug specific
|
|
libxml2.cleanupParser()
|
|
# Note that this can leak memory on Windows if the global state
|
|
# destructors weren't run yet. They should be called eventually,
|
|
# so this leak should be harmless.
|
|
if libxml2.debugMemory(1) == 0:
|
|
print("OK")
|
|
else:
|
|
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|