2001-10-12 17:29:10 +00:00
/**
2008-04-11 12:58:43 +00:00
* threads . c : set of generic threading related routines
2001-10-12 17:29:10 +00:00
*
* See Copyright for the status of this software .
*
* Gary Pennington < Gary . Pennington @ uk . sun . com >
* daniel @ veillard . com
*/
2002-03-18 19:37:11 +00:00
# define IN_LIBXML
2001-10-12 17:29:10 +00:00
# include "libxml.h"
# include <string.h>
2022-03-02 00:29:17 +01:00
# include <stdlib.h>
2001-10-12 17:29:10 +00:00
# include <libxml/threads.h>
2023-09-18 00:54:39 +02:00
# include <libxml/parser.h>
2023-09-18 17:39:13 +02:00
# ifdef LIBXML_CATALOG_ENABLED
# include <libxml/catalog.h>
# endif
# ifdef LIBXML_SCHEMAS_ENABLED
# include <libxml/xmlschemastypes.h>
# include <libxml/relaxng.h>
# endif
2001-10-12 17:29:10 +00:00
# if defined(SOLARIS)
# include <note.h>
# endif
2022-08-26 01:22:33 +02:00
# include "private/dict.h"
2023-09-18 17:39:13 +02:00
# include "private/enc.h"
# include "private/globals.h"
2023-12-20 20:11:09 +01:00
# include "private/io.h"
2023-09-18 17:39:13 +02:00
# include "private/memory.h"
2022-08-26 01:22:33 +02:00
# include "private/threads.h"
2023-09-18 17:39:13 +02:00
# include "private/xpath.h"
2022-08-26 01:22:33 +02:00
2022-10-24 21:50:34 +02:00
# if defined(HAVE_POSIX_THREADS) && \
defined ( __GLIBC__ ) & & \
__GLIBC__ * 100 + __GLIBC_MINOR__ > = 234
2005-05-04 09:18:00 +00:00
2022-10-24 21:50:34 +02:00
/*
* The modern way available since glibc 2.32 .
*
* The check above is for glibc 2.34 which merged the pthread symbols into
* libc . Since we still allow linking without pthread symbols ( see below ) ,
* this only works if pthread symbols are guaranteed to be available .
*/
2017-11-27 14:20:31 +01:00
2022-10-24 21:50:34 +02:00
# include <sys/single_threaded.h>
2017-11-27 14:20:31 +01:00
2022-10-24 21:50:34 +02:00
# define XML_IS_THREADED() (!__libc_single_threaded)
2023-05-03 18:33:20 +02:00
# define XML_IS_NEVER_THREADED() 0
2022-10-24 21:50:34 +02:00
# elif defined(HAVE_POSIX_THREADS) && \
defined ( __GLIBC__ ) & & \
defined ( __GNUC__ )
/*
* The traditional way to check for single - threaded applications with
* glibc was to check whether the separate libpthread library is
* linked in . This works by not linking libxml2 with libpthread ( see
* BASE_THREAD_LIBS in configure . ac and Makefile . am ) and declaring
* pthread functions as weak symbols .
*
* In glibc 2.34 , the pthread symbols were moved from libpthread to libc ,
* so this doesn ' t work anymore .
*
* At some point , this legacy code and the BASE_THREAD_LIBS hack in
* configure . ac can probably be removed .
*/
2017-11-27 14:20:31 +01:00
2022-03-06 19:26:24 +01:00
# pragma weak pthread_mutex_init
2022-03-18 15:46:30 +01:00
# pragma weak pthread_mutex_destroy
2017-06-17 15:05:34 +02:00
# pragma weak pthread_mutex_lock
# pragma weak pthread_mutex_unlock
2022-03-18 15:46:30 +01:00
# pragma weak pthread_cond_init
# pragma weak pthread_cond_destroy
# pragma weak pthread_cond_wait
# pragma weak pthread_equal
2017-06-17 15:05:34 +02:00
# pragma weak pthread_self
2022-03-18 15:46:30 +01:00
# pragma weak pthread_cond_signal
2017-11-27 14:20:31 +01:00
2022-10-24 21:50:34 +02:00
# define XML_PTHREAD_WEAK
# define XML_IS_THREADED() libxml_is_threaded
2023-05-03 18:33:20 +02:00
# define XML_IS_NEVER_THREADED() (!libxml_is_threaded)
2017-11-27 14:20:31 +01:00
2022-10-24 21:50:34 +02:00
static int libxml_is_threaded = - 1 ;
2017-11-27 14:20:31 +01:00
2022-10-24 21:50:34 +02:00
# else /* other POSIX platforms */
2017-11-27 14:20:31 +01:00
2022-10-24 21:50:34 +02:00
# define XML_IS_THREADED() 1
2023-05-03 18:33:20 +02:00
# define XML_IS_NEVER_THREADED() 0
2022-10-24 21:50:34 +02:00
# endif
2005-05-04 09:18:00 +00:00
2001-10-12 17:29:10 +00:00
/*
* TODO : this module still uses malloc / free and not xmlMalloc / xmlFree
2019-09-30 17:04:54 +02:00
* to avoid some craziness since xmlMalloc / xmlFree may actually
2001-10-12 17:29:10 +00:00
* be hosted on allocated blocks needing them for the allocation . . .
*/
/*
* xmlRMutex are reentrant mutual exception locks
*/
struct _xmlRMutex {
2022-09-04 01:49:41 +02:00
# ifdef HAVE_POSIX_THREADS
2001-10-12 17:29:10 +00:00
pthread_mutex_t lock ;
2022-03-18 15:46:30 +01:00
unsigned int held ;
unsigned int waiters ;
pthread_t tid ;
pthread_cond_t cv ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
CRITICAL_SECTION cs ;
2001-10-12 17:29:10 +00:00
# else
int empty ;
# endif
} ;
2008-03-18 08:24:25 +00:00
static xmlRMutexPtr xmlLibraryLock = NULL ;
2022-11-24 20:54:18 +01:00
/**
* xmlInitMutex :
* @ mutex : the mutex
*
* Initialize a mutex .
*/
void
xmlInitMutex ( xmlMutexPtr mutex )
{
# ifdef HAVE_POSIX_THREADS
2023-05-03 18:33:20 +02:00
if ( XML_IS_NEVER_THREADED ( ) = = 0 )
pthread_mutex_init ( & mutex - > lock , NULL ) ;
2022-11-24 20:54:18 +01:00
# elif defined HAVE_WIN32_THREADS
InitializeCriticalSection ( & mutex - > cs ) ;
# else
( void ) mutex ;
# endif
}
2001-10-12 17:29:10 +00:00
/**
2002-12-10 15:19:08 +00:00
* xmlNewMutex :
2001-10-12 17:29:10 +00:00
*
* xmlNewMutex ( ) is used to allocate a libxml2 token struct for use in
* synchronizing access to data .
*
* Returns a new simple mutex pointer or NULL in case of error
*/
xmlMutexPtr
xmlNewMutex ( void )
{
xmlMutexPtr tok ;
if ( ( tok = malloc ( sizeof ( xmlMutex ) ) ) = = NULL )
return ( NULL ) ;
2022-11-24 20:54:18 +01:00
xmlInitMutex ( tok ) ;
return ( tok ) ;
}
/**
* xmlCleanupMutex :
* @ mutex : the simple mutex
*
* Reclaim resources associated with a mutex .
*/
void
xmlCleanupMutex ( xmlMutexPtr mutex )
{
2022-09-04 01:49:41 +02:00
# ifdef HAVE_POSIX_THREADS
2023-05-03 18:33:20 +02:00
if ( XML_IS_NEVER_THREADED ( ) = = 0 )
pthread_mutex_destroy ( & mutex - > lock ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2022-11-24 20:54:18 +01:00
DeleteCriticalSection ( & mutex - > cs ) ;
# else
( void ) mutex ;
2001-10-12 17:29:10 +00:00
# endif
}
/**
* xmlFreeMutex :
* @ tok : the simple mutex
*
2022-11-24 20:54:18 +01:00
* Free a mutex .
2001-10-12 17:29:10 +00:00
*/
void
xmlFreeMutex ( xmlMutexPtr tok )
{
2008-03-18 08:24:25 +00:00
if ( tok = = NULL )
return ;
2003-07-08 14:03:36 +00:00
2022-11-24 20:54:18 +01:00
xmlCleanupMutex ( tok ) ;
2001-10-12 17:29:10 +00:00
free ( tok ) ;
}
/**
* xmlMutexLock :
* @ tok : the simple mutex
*
* xmlMutexLock ( ) is used to lock a libxml2 token .
*/
void
2003-08-08 14:00:28 +00:00
xmlMutexLock ( xmlMutexPtr tok )
2001-10-12 17:29:10 +00:00
{
2003-08-08 14:00:28 +00:00
if ( tok = = NULL )
return ;
2022-09-04 01:49:41 +02:00
# ifdef HAVE_POSIX_THREADS
2022-10-24 21:50:34 +02:00
/*
* This assumes that __libc_single_threaded won ' t change while the
* lock is held .
*/
if ( XML_IS_THREADED ( ) ! = 0 )
2008-03-18 08:24:25 +00:00
pthread_mutex_lock ( & tok - > lock ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2022-03-06 15:12:08 +01:00
EnterCriticalSection ( & tok - > cs ) ;
2001-10-12 17:29:10 +00:00
# endif
}
/**
* xmlMutexUnlock :
* @ tok : the simple mutex
*
* xmlMutexUnlock ( ) is used to unlock a libxml2 token .
*/
void
2003-08-28 08:03:23 +00:00
xmlMutexUnlock ( xmlMutexPtr tok )
2001-10-12 17:29:10 +00:00
{
2003-08-28 08:03:23 +00:00
if ( tok = = NULL )
return ;
2022-09-04 01:49:41 +02:00
# ifdef HAVE_POSIX_THREADS
2022-10-24 21:50:34 +02:00
if ( XML_IS_THREADED ( ) ! = 0 )
2008-03-18 08:24:25 +00:00
pthread_mutex_unlock ( & tok - > lock ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2022-03-06 15:12:08 +01:00
LeaveCriticalSection ( & tok - > cs ) ;
2001-10-12 17:29:10 +00:00
# endif
}
/**
2002-12-10 15:19:08 +00:00
* xmlNewRMutex :
2001-10-12 17:29:10 +00:00
*
* xmlRNewMutex ( ) is used to allocate a reentrant mutex for use in
* synchronizing access to data . token_r is a re - entrant lock and thus useful
* for synchronizing access to data structures that may be manipulated in a
* recursive fashion .
*
* Returns the new reentrant mutex pointer or NULL in case of error
*/
xmlRMutexPtr
xmlNewRMutex ( void )
{
xmlRMutexPtr tok ;
if ( ( tok = malloc ( sizeof ( xmlRMutex ) ) ) = = NULL )
return ( NULL ) ;
2022-09-04 01:49:41 +02:00
# ifdef HAVE_POSIX_THREADS
2023-05-03 18:33:20 +02:00
if ( XML_IS_NEVER_THREADED ( ) = = 0 ) {
pthread_mutex_init ( & tok - > lock , NULL ) ;
tok - > held = 0 ;
tok - > waiters = 0 ;
pthread_cond_init ( & tok - > cv , NULL ) ;
}
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
InitializeCriticalSection ( & tok - > cs ) ;
2001-10-12 17:29:10 +00:00
# endif
return ( tok ) ;
}
/**
2002-12-10 15:19:08 +00:00
* xmlFreeRMutex :
2001-10-12 17:29:10 +00:00
* @ tok : the reentrant mutex
*
* xmlRFreeMutex ( ) is used to reclaim resources associated with a
* reentrant mutex .
*/
void
2002-02-10 13:20:39 +00:00
xmlFreeRMutex ( xmlRMutexPtr tok ATTRIBUTE_UNUSED )
2001-10-12 17:29:10 +00:00
{
2005-05-04 09:18:00 +00:00
if ( tok = = NULL )
return ;
2022-09-04 01:49:41 +02:00
# ifdef HAVE_POSIX_THREADS
2023-05-03 18:33:20 +02:00
if ( XML_IS_NEVER_THREADED ( ) = = 0 ) {
pthread_mutex_destroy ( & tok - > lock ) ;
pthread_cond_destroy ( & tok - > cv ) ;
}
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
DeleteCriticalSection ( & tok - > cs ) ;
2001-10-12 17:29:10 +00:00
# endif
free ( tok ) ;
}
/**
* xmlRMutexLock :
* @ tok : the reentrant mutex
*
* xmlRMutexLock ( ) is used to lock a libxml2 token_r .
*/
void
2003-09-11 23:35:09 +00:00
xmlRMutexLock ( xmlRMutexPtr tok )
2001-10-12 17:29:10 +00:00
{
2003-09-11 23:35:09 +00:00
if ( tok = = NULL )
return ;
2022-09-04 01:49:41 +02:00
# ifdef HAVE_POSIX_THREADS
2022-10-24 21:50:34 +02:00
if ( XML_IS_THREADED ( ) = = 0 )
2022-03-18 15:46:30 +01:00
return ;
pthread_mutex_lock ( & tok - > lock ) ;
if ( tok - > held ) {
if ( pthread_equal ( tok - > tid , pthread_self ( ) ) ) {
tok - > held + + ;
pthread_mutex_unlock ( & tok - > lock ) ;
return ;
} else {
tok - > waiters + + ;
while ( tok - > held )
pthread_cond_wait ( & tok - > cv , & tok - > lock ) ;
tok - > waiters - - ;
}
}
tok - > tid = pthread_self ( ) ;
tok - > held = 1 ;
pthread_mutex_unlock ( & tok - > lock ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
EnterCriticalSection ( & tok - > cs ) ;
2001-10-12 17:29:10 +00:00
# endif
}
/**
* xmlRMutexUnlock :
* @ tok : the reentrant mutex
*
* xmlRMutexUnlock ( ) is used to unlock a libxml2 token_r .
*/
void
2002-02-10 13:20:39 +00:00
xmlRMutexUnlock ( xmlRMutexPtr tok ATTRIBUTE_UNUSED )
2001-10-12 17:29:10 +00:00
{
2003-09-11 23:35:09 +00:00
if ( tok = = NULL )
return ;
2022-09-04 01:49:41 +02:00
# ifdef HAVE_POSIX_THREADS
2022-10-24 21:50:34 +02:00
if ( XML_IS_THREADED ( ) = = 0 )
2022-03-18 15:46:30 +01:00
return ;
pthread_mutex_lock ( & tok - > lock ) ;
tok - > held - - ;
if ( tok - > held = = 0 ) {
if ( tok - > waiters )
pthread_cond_signal ( & tok - > cv ) ;
memset ( & tok - > tid , 0 , sizeof ( tok - > tid ) ) ;
}
pthread_mutex_unlock ( & tok - > lock ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2022-03-06 15:12:08 +01:00
LeaveCriticalSection ( & tok - > cs ) ;
2001-10-12 17:29:10 +00:00
# endif
}
/************************************************************************
* *
* Library wide thread interfaces *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-17 15:58:35 +00:00
/**
* xmlGetThreadId :
*
2022-11-24 15:00:03 +01:00
* DEPRECATED : Internal function , do not use .
*
2001-10-17 15:58:35 +00:00
* xmlGetThreadId ( ) find the current thread ID number
2009-09-10 17:46:07 +02:00
* Note that this is likely to be broken on some platforms using pthreads
* as the specification doesn ' t mandate pthread_t to be an integer type
2001-10-17 15:58:35 +00:00
*
* Returns the current thread ID number
*/
int
xmlGetThreadId ( void )
{
2022-09-04 01:49:41 +02:00
# ifdef HAVE_POSIX_THREADS
2009-09-10 17:46:07 +02:00
pthread_t id ;
int ret ;
2022-10-24 21:50:34 +02:00
if ( XML_IS_THREADED ( ) = = 0 )
2008-03-18 08:24:25 +00:00
return ( 0 ) ;
2009-09-10 17:46:07 +02:00
id = pthread_self ( ) ;
/* horrible but preserves compat, see warning above */
memcpy ( & ret , & id , sizeof ( ret ) ) ;
return ( ret ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
return GetCurrentThreadId ( ) ;
2001-10-17 15:58:35 +00:00
# else
2008-03-18 08:24:25 +00:00
return ( ( int ) 0 ) ;
2001-10-17 15:58:35 +00:00
# endif
}
2001-10-12 17:29:10 +00:00
/**
* xmlLockLibrary :
*
* xmlLockLibrary ( ) is used to take out a re - entrant lock on the libxml2
* library .
*/
void
xmlLockLibrary ( void )
{
xmlRMutexLock ( xmlLibraryLock ) ;
}
/**
* xmlUnlockLibrary :
*
* xmlUnlockLibrary ( ) is used to release a re - entrant lock on the libxml2
* library .
*/
void
xmlUnlockLibrary ( void )
{
xmlRMutexUnlock ( xmlLibraryLock ) ;
}
/**
* xmlInitThreads :
*
2022-11-25 12:06:27 +01:00
* DEPRECATED : Alias for xmlInitParser .
2001-10-12 17:29:10 +00:00
*/
void
xmlInitThreads ( void )
2022-11-25 12:06:27 +01:00
{
xmlInitParser ( ) ;
}
2023-09-18 17:39:13 +02:00
/**
* xmlCleanupThreads :
*
* DEPRECATED : This function is a no - op . Call xmlCleanupParser
* to free global state but see the warnings there . xmlCleanupParser
* should be only called once at program exit . In most cases , you don ' t
* have call cleanup functions at all .
*/
void
xmlCleanupThreads ( void )
{
}
/************************************************************************
* *
* Library wide initialization *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int xmlParserInitialized = 0 ;
2023-09-27 17:22:17 +02:00
static int xmlParserInnerInitialized = 0 ;
2023-09-18 17:39:13 +02:00
# ifdef HAVE_POSIX_THREADS
static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER ;
# elif defined HAVE_WIN32_THREADS
static volatile LPCRITICAL_SECTION global_init_lock = NULL ;
# endif
/**
* xmlGlobalInitMutexLock
*
* Makes sure that the global initialization mutex is initialized and
* locks it .
*/
static void
xmlGlobalInitMutexLock ( void ) {
# ifdef HAVE_POSIX_THREADS
2017-11-27 14:20:31 +01:00
# ifdef XML_PTHREAD_WEAK
2022-10-24 21:50:34 +02:00
/*
* This is somewhat unreliable since libpthread could be loaded
* later with dlopen ( ) and threads could be created . But it ' s
* long - standing behavior and hard to work around .
*/
if ( libxml_is_threaded = = - 1 )
2023-02-23 14:26:32 +01:00
libxml_is_threaded =
( pthread_mutex_init ! = NULL ) & &
( pthread_mutex_destroy ! = NULL ) & &
( pthread_mutex_lock ! = NULL ) & &
( pthread_mutex_unlock ! = NULL ) & &
( pthread_cond_init ! = NULL ) & &
( pthread_cond_destroy ! = NULL ) & &
( pthread_cond_wait ! = NULL ) & &
/*
* pthread_equal can be inline , resuting in - Waddress warnings .
* Let ' s assume it ' s available if all the other functions are .
*/
/* (pthread_equal != NULL) && */
( pthread_self ! = NULL ) & &
( pthread_cond_signal ! = NULL ) ;
2023-09-18 17:39:13 +02:00
# endif
/* The mutex is statically initialized, so we just lock it. */
if ( XML_IS_THREADED ( ) ! = 0 )
pthread_mutex_lock ( & global_init_lock ) ;
# elif defined HAVE_WIN32_THREADS
LPCRITICAL_SECTION cs ;
/* Create a new critical section */
if ( global_init_lock = = NULL ) {
cs = malloc ( sizeof ( CRITICAL_SECTION ) ) ;
if ( cs = = NULL ) {
2023-12-18 21:32:49 +01:00
fprintf ( stderr , " libxml2: xmlInitParser: out of memory \n " ) ;
abort ( ) ;
2023-09-18 17:39:13 +02:00
}
InitializeCriticalSection ( cs ) ;
/* Swap it into the global_init_lock */
# ifdef InterlockedCompareExchangePointer
InterlockedCompareExchangePointer ( ( void * * ) & global_init_lock ,
cs , NULL ) ;
# else /* Use older void* version */
InterlockedCompareExchange ( ( void * * ) & global_init_lock ,
( void * ) cs , NULL ) ;
# endif /* InterlockedCompareExchangePointer */
/* If another thread successfully recorded its critical
* section in the global_init_lock then discard the one
* allocated by this thread . */
if ( global_init_lock ! = cs ) {
DeleteCriticalSection ( cs ) ;
free ( cs ) ;
}
}
/* Lock the chosen critical section */
EnterCriticalSection ( global_init_lock ) ;
# endif
}
static void
xmlGlobalInitMutexUnlock ( void ) {
# ifdef HAVE_POSIX_THREADS
if ( XML_IS_THREADED ( ) ! = 0 )
pthread_mutex_unlock ( & global_init_lock ) ;
# elif defined HAVE_WIN32_THREADS
if ( global_init_lock ! = NULL )
LeaveCriticalSection ( global_init_lock ) ;
2005-05-04 09:18:00 +00:00
# endif
2001-10-12 17:29:10 +00:00
}
/**
2023-09-18 17:39:13 +02:00
* xmlGlobalInitMutexDestroy
2001-10-12 17:29:10 +00:00
*
2023-09-18 17:39:13 +02:00
* Makes sure that the global initialization mutex is destroyed before
* application termination .
*/
static void
xmlGlobalInitMutexDestroy ( void ) {
# ifdef HAVE_POSIX_THREADS
# elif defined HAVE_WIN32_THREADS
if ( global_init_lock ! = NULL ) {
DeleteCriticalSection ( global_init_lock ) ;
free ( global_init_lock ) ;
global_init_lock = NULL ;
}
# endif
}
/**
* xmlInitParser :
*
* Initialization function for the XML parser .
*
* Call once from the main thread before using the library in
* multithreaded programs .
2001-10-12 17:29:10 +00:00
*/
void
2023-09-18 17:39:13 +02:00
xmlInitParser ( void ) {
/*
* Note that the initialization code must not make memory allocations .
*/
if ( xmlParserInitialized ! = 0 )
return ;
xmlGlobalInitMutexLock ( ) ;
2023-09-27 17:22:17 +02:00
if ( xmlParserInnerInitialized = = 0 ) {
2023-09-18 17:39:13 +02:00
# if defined(_WIN32) && \
2023-10-18 20:06:35 +02:00
! defined ( LIBXML_THREAD_ALLOC_ENABLED ) & & \
2023-09-18 17:39:13 +02:00
( ! defined ( LIBXML_STATIC ) | | defined ( LIBXML_STATIC_FOR_DLL ) )
if ( xmlFree = = free )
atexit ( xmlCleanupParser ) ;
# endif
2023-12-24 15:33:12 +01:00
xmlInitRandom ( ) ; /* Required by xmlInitGlobalsInternal */
xmlInitMemoryInternal ( ) ;
2023-09-18 17:39:13 +02:00
xmlInitGlobalsInternal ( ) ;
xmlInitDictInternal ( ) ;
xmlInitEncodingInternal ( ) ;
# if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
xmlInitXPathInternal ( ) ;
# endif
2023-12-20 20:11:09 +01:00
xmlInitIOCallbacks ( ) ;
2023-09-18 17:39:13 +02:00
2023-09-27 17:22:17 +02:00
xmlParserInnerInitialized = 1 ;
2023-09-18 17:39:13 +02:00
}
xmlGlobalInitMutexUnlock ( ) ;
2023-09-19 17:21:30 +02:00
xmlParserInitialized = 1 ;
2022-11-25 12:06:27 +01:00
}
/**
2023-09-18 17:39:13 +02:00
* xmlCleanupParser :
*
* This function name is somewhat misleading . It does not clean up
* parser state , it cleans up memory allocated by the library itself .
* It is a cleanup function for the XML library . It tries to reclaim all
* related global memory allocated for the library processing .
* It doesn ' t deallocate any document related memory . One should
* call xmlCleanupParser ( ) only when the process has finished using
* the library and all XML / HTML documents built with it .
* See also xmlInitParser ( ) which has the opposite function of preparing
* the library for operations .
2022-11-25 12:06:27 +01:00
*
2023-09-18 17:39:13 +02:00
* WARNING : if your application is multithreaded or has plugin support
* calling this may crash the application if another thread or
* a plugin is still using libxml2 . It ' s sometimes very hard to
* guess if libxml2 is in use in the application , some libraries
* or plugins may use it without notice . In case of doubt abstain
* from calling this function or do it just before calling exit ( )
* to avoid leak reports from valgrind !
2022-11-25 12:06:27 +01:00
*/
void
2023-09-18 17:39:13 +02:00
xmlCleanupParser ( void ) {
if ( ! xmlParserInitialized )
return ;
/* These functions can call xmlFree. */
xmlCleanupCharEncodingHandlers ( ) ;
# ifdef LIBXML_CATALOG_ENABLED
xmlCatalogCleanup ( ) ;
# endif
# ifdef LIBXML_SCHEMAS_ENABLED
xmlSchemaCleanupTypes ( ) ;
xmlRelaxNGCleanupTypes ( ) ;
# endif
/* These functions should never call xmlFree. */
xmlCleanupDictInternal ( ) ;
2023-09-16 19:08:10 +02:00
xmlCleanupRandom ( ) ;
2023-09-18 17:39:13 +02:00
xmlCleanupGlobalsInternal ( ) ;
/*
* Must come last . On Windows , xmlCleanupGlobalsInternal can call
* xmlFree which uses xmlMemMutex in debug mode .
*/
xmlCleanupMemoryInternal ( ) ;
xmlGlobalInitMutexDestroy ( ) ;
xmlParserInitialized = 0 ;
2023-09-27 17:22:17 +02:00
xmlParserInnerInitialized = 0 ;
2001-10-12 17:29:10 +00:00
}
2003-05-17 10:55:15 +00:00
2023-10-18 20:06:35 +02:00
# if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && \
! defined ( LIBXML_THREAD_ALLOC_ENABLED ) & & \
! defined ( LIBXML_STATIC ) & & \
2023-09-18 17:39:13 +02:00
! defined ( _WIN32 )
static void
ATTRIBUTE_DESTRUCTOR
xmlDestructor ( void ) {
/*
* Calling custom deallocation functions in a destructor can cause
* problems , for example with Nokogiri .
*/
if ( xmlFree = = free )
xmlCleanupParser ( ) ;
}
# endif