1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-10-24 13:33:01 +03:00

globals: Introduce xmlCheckThreadLocalStorage

Checks whether (emulated) thread-local storage could be allocated.
This commit is contained in:
Nick Wellnhofer
2023-09-18 19:53:31 +02:00
parent 89f4976728
commit bf6bd16154
3 changed files with 72 additions and 49 deletions

View File

@@ -806,6 +806,31 @@ xmlNewGlobalState(void)
} }
#endif /* LIBXML_THREAD_ENABLED */ #endif /* LIBXML_THREAD_ENABLED */
/**
* xmlCheckThreadLocalStorage:
*
* Check whether thread-local storage could be allocated.
*
* In multithreaded environments, this function should be called once
* in each thread before calling other library functions to make sure
* that thread-local storage was allocated properly.
*
* Returns 0 on success or -1 if a memory allocation failed. A failed
* allocation signals a typically fatal and irrecoverable out-of-memory
* situation. Don't call any library functions in this case.
*
* This function never fails for the "main" thread which is the first
* thread calling xmlInitParser.
*
* Available since v2.12.0.
*/
int
xmlCheckThreadLocalStorage(void) {
if (IS_MAIN_THREAD)
return(0);
return((xmlGetGlobalState() == NULL) ? -1 : 0);
}
/** /**
* xmlGetGlobalState: * xmlGetGlobalState:
* *

View File

@@ -82,6 +82,7 @@ typedef void (*xmlDeregisterNodeFunc) (xmlNodePtr node);
typedef struct _xmlGlobalState xmlGlobalState; typedef struct _xmlGlobalState xmlGlobalState;
typedef xmlGlobalState *xmlGlobalStatePtr; typedef xmlGlobalState *xmlGlobalStatePtr;
XMLPUBFUN int xmlCheckThreadLocalStorage(void);
XML_DEPRECATED XML_DEPRECATED
XMLPUBFUN void xmlInitializeGlobalState(xmlGlobalStatePtr gs); XMLPUBFUN void xmlInitializeGlobalState(xmlGlobalStatePtr gs);
XML_DEPRECATED XML_DEPRECATED

View File

@@ -3,10 +3,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
#include <libxml/globals.h>
#include <libxml/threads.h>
#include <libxml/parser.h> #include <libxml/parser.h>
#include <libxml/threads.h>
#include <libxml/globals.h>
#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
#include <libxml/catalog.h> #include <libxml/catalog.h>
#ifdef HAVE_PTHREAD_H #ifdef HAVE_PTHREAD_H
#include <pthread.h> #include <pthread.h>
@@ -57,6 +58,12 @@ thread_specific_data(void *private_data)
const char *filename = params->filename; const char *filename = params->filename;
int okay = 1; int okay = 1;
if (xmlCheckThreadLocalStorage() != 0) {
printf("xmlCheckThreadLocalStorage failed\n");
params->okay = 0;
return(NULL);
}
if (!strcmp(filename, "test/threads/invalid.xml")) { if (!strcmp(filename, "test/threads/invalid.xml")) {
xmlDoValidityCheckingDefaultValue = 0; xmlDoValidityCheckingDefaultValue = 0;
xmlGenericErrorContext = stdout; xmlGenericErrorContext = stdout;
@@ -98,17 +105,39 @@ thread_specific_data(void *private_data)
return(NULL); return(NULL);
} }
#ifdef HAVE_PTHREAD_H #ifdef _WIN32
static DWORD WINAPI
win32_thread_specific_data(void *private_data)
{
thread_specific_data(private_data);
return(0);
}
#endif
#endif /* LIBXML_THREADS_ENABLED */
int int
main(void) main(void)
{ {
unsigned int i, repeat; unsigned int repeat;
int ret; int status = 0;
(void) repeat;
xmlInitParser(); xmlInitParser();
if (xmlCheckThreadLocalStorage() != 0) {
printf("xmlCheckThreadLocalStorage failed for main thread\n");
return(1);
}
#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
for (repeat = 0;repeat < TEST_REPEAT_COUNT;repeat++) { for (repeat = 0;repeat < TEST_REPEAT_COUNT;repeat++) {
unsigned int i;
int ret;
xmlLoadCatalog(catalog); xmlLoadCatalog(catalog);
#ifdef HAVE_PTHREAD_H
memset(tid, 0xff, sizeof(*tid)*num_threads); memset(tid, 0xff, sizeof(*tid)*num_threads);
for (i = 0; i < num_threads; i++) { for (i = 0; i < num_threads; i++) {
@@ -127,35 +156,7 @@ main(void)
exit(1); exit(1);
} }
} }
xmlCatalogCleanup();
for (i = 0; i < num_threads; i++)
if (threadParams[i].okay == 0)
printf("Thread %d handling %s failed\n", i,
threadParams[i].filename);
}
xmlCleanupParser();
return (0);
}
#elif defined(_WIN32) #elif defined(_WIN32)
static DWORD WINAPI
win32_thread_specific_data(void *private_data)
{
thread_specific_data(private_data);
return(0);
}
int
main(void)
{
unsigned int i, repeat;
BOOL ret;
xmlInitParser();
for (repeat = 0;repeat < TEST_REPEAT_COUNT;repeat++)
{
xmlLoadCatalog(catalog);
for (i = 0; i < num_threads; i++) for (i = 0; i < num_threads; i++)
{ {
tid[i] = (HANDLE) -1; tid[i] = (HANDLE) -1;
@@ -187,26 +188,22 @@ main(void)
} }
CloseHandle (tid[i]); CloseHandle (tid[i]);
} }
#endif /* pthreads */
xmlCatalogCleanup(); xmlCatalogCleanup();
for (i = 0; i < num_threads; i++) {
if (threadParams[i].okay == 0) for (i = 0; i < num_threads; i++) {
printf("Thread %d handling %s failed\n", i, if (threadParams[i].okay == 0) {
threadParams[i].filename); printf("Thread %d handling %s failed\n", i,
threadParams[i].filename);
status = 1;
}
} }
} }
#endif /* LIBXML_THREADS_ENABLED */
xmlCleanupParser(); xmlCleanupParser();
return (0); return (status);
} }
#endif /* pthreads */
#else /* !LIBXML_THREADS_ENABLED */
int
main(void)
{
fprintf(stderr, "libxml was not compiled with thread or catalog support\n");
return (0);
}
#endif