1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-10-23 01:52:48 +03:00
Files
libxml2/python/tests/thread2.py
Nick Wellnhofer fc26934eb0 memory: Fix memory debugging with Windows threads
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.
2023-09-21 23:29:18 +02:00

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)))