VirtualBox

source: vbox/trunk/src/libs/libxml2-2.12.6/globals.c

Last change on this file was 104106, checked in by vboxsync, 8 weeks ago

libxml2-2.9.14: Applied and adjusted our libxml2 changes to 2.9.14. bugref:10640

  • Property svn:eol-style set to native
File size: 31.4 KB
Line 
1/*
2 * globals.c: definition and handling of the set of global variables
3 * of the library
4 *
5 * See Copyright for the status of this software.
6 *
7 * Gary Pennington <Gary.Pennington@uk.sun.com>
8 * daniel@veillard.com
9 */
10
11#define IN_LIBXML
12#include "libxml.h"
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17
18#define XML_GLOBALS_NO_REDEFINITION
19#include <libxml/globals.h>
20#include <libxml/xmlerror.h>
21#include <libxml/xmlmemory.h>
22#include <libxml/xmlIO.h>
23#include <libxml/HTMLparser.h>
24#include <libxml/parser.h>
25#include <libxml/threads.h>
26#include <libxml/tree.h>
27#include <libxml/SAX.h>
28#include <libxml/SAX2.h>
29
30#include "private/error.h"
31#include "private/globals.h"
32#include "private/threads.h"
33#include "private/tree.h"
34
35/*
36 * Thread-local storage emulation.
37 *
38 * This works by replacing a global variable
39 *
40 * extern xmlError xmlLastError;
41 *
42 * with a macro that calls a function returning a pointer to the global in
43 * thread-local storage:
44 *
45 * xmlError *__xmlLastError(void);
46 * #define xmlError (*__xmlLastError());
47 *
48 * The code can operate in a multitude of ways depending on the environment.
49 * First we support POSIX and Windows threads. Then we support both thread-local
50 * storage provided by the compiler and older methods like thread-specific data
51 * (pthreads) or TlsAlloc (Windows).
52 *
53 * To clean up thread-local storage, we use thread-specific data on POSIX.
54 * On Windows, we either use DllMain when compiling a DLL or a registered wait
55 * function for static builds.
56 */
57
58/*
59 * Helpful Macro
60 */
61#ifdef LIBXML_THREAD_ENABLED
62#define IS_MAIN_THREAD (xmlIsMainThreadInternal())
63#else
64#define IS_MAIN_THREAD 1
65#endif
66
67#define XML_DECLARE_MEMBER(name, type, attrs) \
68 type gs_##name;
69
70struct _xmlGlobalState {
71 int initialized;
72
73#if defined(HAVE_WIN32_THREADS) && \
74 defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
75 void *threadHandle;
76 void *waitHandle;
77#endif
78
79#define XML_OP XML_DECLARE_MEMBER
80XML_GLOBALS_ALLOC
81XML_GLOBALS_ERROR
82XML_GLOBALS_HTML
83XML_GLOBALS_IO
84XML_GLOBALS_PARSER
85XML_GLOBALS_TREE
86#undef XML_OP
87};
88
89static int parserInitialized;
90
91/*
92 * Mutex to protect "ForNewThreads" variables
93 */
94static xmlMutex xmlThrDefMutex;
95
96#ifdef LIBXML_THREAD_ENABLED
97
98/*
99 * On Darwin, thread-local storage destructors seem to be run before
100 * pthread thread-specific data destructors. This causes ASan to
101 * report a use-after-free.
102 *
103 * On Windows, we can't use TLS in static builds. The RegisterWait
104 * callback would run after TLS was deallocated.
105 */
106#if defined(XML_THREAD_LOCAL) && \
107 !defined(__APPLE__) && \
108 (!defined(HAVE_WIN32_THREADS) || \
109 !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
110#define USE_TLS
111#endif
112
113#ifdef USE_TLS
114static XML_THREAD_LOCAL xmlGlobalState globalState;
115#endif
116
117#ifdef HAVE_POSIX_THREADS
118
119/*
120 * Weak symbol hack, see threads.c
121 */
122#if defined(__GNUC__) && \
123 defined(__GLIBC__) && \
124 __GLIBC__ * 100 + __GLIBC_MINOR__ < 234
125
126#pragma weak pthread_getspecific
127#pragma weak pthread_setspecific
128#pragma weak pthread_key_create
129#pragma weak pthread_key_delete
130#pragma weak pthread_equal
131#pragma weak pthread_self
132
133#define XML_PTHREAD_WEAK
134
135static int libxml_is_threaded = -1;
136
137#endif
138
139/*
140 * On POSIX, we need thread-specific data even with thread-local storage
141 * to destroy indirect references from global state (xmlLastError) at
142 * thread exit.
143 */
144static pthread_key_t globalkey;
145static pthread_t mainthread;
146
147#elif defined HAVE_WIN32_THREADS
148
149#ifndef USE_TLS
150static DWORD globalkey = TLS_OUT_OF_INDEXES;
151#endif
152static DWORD mainthread;
153
154#endif /* HAVE_WIN32_THREADS */
155
156static void
157xmlFreeGlobalState(void *state);
158
159#endif /* LIBXML_THREAD_ENABLED */
160
161/************************************************************************
162 * *
163 * All the user accessible global variables of the library *
164 * *
165 ************************************************************************/
166
167/*
168 * Memory allocation routines
169 */
170
171#if defined(DEBUG_MEMORY_LOCATION)
172xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
173xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
174xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc;
175xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
176xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
177#else
178/**
179 * xmlFree:
180 * @mem: an already allocated block of memory
181 *
182 * The variable holding the libxml free() implementation
183 */
184xmlFreeFunc xmlFree = free;
185/**
186 * xmlMalloc:
187 * @size: the size requested in bytes
188 *
189 * The variable holding the libxml malloc() implementation
190 *
191 * Returns a pointer to the newly allocated block or NULL in case of error
192 */
193xmlMallocFunc xmlMalloc = malloc;
194/**
195 * xmlMallocAtomic:
196 * @size: the size requested in bytes
197 *
198 * The variable holding the libxml malloc() implementation for atomic
199 * data (i.e. blocks not containing pointers), useful when using a
200 * garbage collecting allocator.
201 *
202 * Returns a pointer to the newly allocated block or NULL in case of error
203 */
204xmlMallocFunc xmlMallocAtomic = malloc;
205/**
206 * xmlRealloc:
207 * @mem: an already allocated block of memory
208 * @size: the new size requested in bytes
209 *
210 * The variable holding the libxml realloc() implementation
211 *
212 * Returns a pointer to the newly reallocated block or NULL in case of error
213 */
214xmlReallocFunc xmlRealloc = realloc;
215/**
216 * xmlPosixStrdup
217 * @cur: the input char *
218 *
219 * a strdup implementation with a type signature matching POSIX
220 *
221 * Returns a new xmlChar * or NULL
222 */
223static char *
224xmlPosixStrdup(const char *cur) {
225 return((char*) xmlCharStrdup(cur));
226}
227/**
228 * xmlMemStrdup:
229 * @str: a zero terminated string
230 *
231 * The variable holding the libxml strdup() implementation
232 *
233 * Returns the copy of the string or NULL in case of error
234 */
235xmlStrdupFunc xmlMemStrdup = xmlPosixStrdup;
236#endif /* DEBUG_MEMORY_LOCATION */
237
238/**
239 * xmlBufferAllocScheme:
240 *
241 * DEPRECATED: Don't use.
242 *
243 * Global setting, default allocation policy for buffers, default is
244 * XML_BUFFER_ALLOC_EXACT
245 */
246xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
247static xmlBufferAllocationScheme xmlBufferAllocSchemeThrDef = XML_BUFFER_ALLOC_EXACT;
248/**
249 * xmlDefaultBufferSize:
250 *
251 * DEPRECATED: Don't use.
252 *
253 * Global setting, default buffer size. Default value is BASE_BUFFER_SIZE
254 */
255int xmlDefaultBufferSize = BASE_BUFFER_SIZE;
256static int xmlDefaultBufferSizeThrDef = BASE_BUFFER_SIZE;
257
258/*
259 * Parser defaults
260 */
261
262/**
263 * oldXMLWDcompatibility:
264 *
265 * Global setting, DEPRECATED.
266 */
267int oldXMLWDcompatibility = 0; /* DEPRECATED */
268/**
269 * xmlParserDebugEntities:
270 *
271 * DEPRECATED: Don't use
272 *
273 * Global setting, asking the parser to print out debugging information.
274 * while handling entities.
275 * Disabled by default
276 */
277int xmlParserDebugEntities = 0;
278static int xmlParserDebugEntitiesThrDef = 0;
279/**
280 * xmlDoValidityCheckingDefaultValue:
281 *
282 * DEPRECATED: Use the modern options API with XML_PARSE_DTDVALID.
283 *
284 * Global setting, indicate that the parser should work in validating mode.
285 * Disabled by default.
286 */
287int xmlDoValidityCheckingDefaultValue = 0;
288static int xmlDoValidityCheckingDefaultValueThrDef = 0;
289/**
290 * xmlGetWarningsDefaultValue:
291 *
292 * DEPRECATED: Don't use
293 *
294 * Global setting, indicate that the DTD validation should provide warnings.
295 * Activated by default.
296 */
297int xmlGetWarningsDefaultValue = 1;
298static int xmlGetWarningsDefaultValueThrDef = 1;
299/**
300 * xmlLoadExtDtdDefaultValue:
301 *
302 * DEPRECATED: Use the modern options API with XML_PARSE_DTDLOAD.
303 *
304 * Global setting, indicate that the parser should load DTD while not
305 * validating.
306 * Disabled by default.
307 */
308int xmlLoadExtDtdDefaultValue = 0;
309static int xmlLoadExtDtdDefaultValueThrDef = 0;
310/**
311 * xmlPedanticParserDefaultValue:
312 *
313 * DEPRECATED: Use the modern options API with XML_PARSE_PEDANTIC.
314 *
315 * Global setting, indicate that the parser be pedantic
316 * Disabled by default.
317 */
318int xmlPedanticParserDefaultValue = 0;
319static int xmlPedanticParserDefaultValueThrDef = 0;
320/**
321 * xmlLineNumbersDefaultValue:
322 *
323 * DEPRECATED: The modern options API always enables line numbers.
324 *
325 * Global setting, indicate that the parser should store the line number
326 * in the content field of elements in the DOM tree.
327 * Disabled by default since this may not be safe for old classes of
328 * application.
329 */
330int xmlLineNumbersDefaultValue = 0;
331static int xmlLineNumbersDefaultValueThrDef = 0;
332/**
333 * xmlKeepBlanksDefaultValue:
334 *
335 * DEPRECATED: Use the modern options API with XML_PARSE_NOBLANKS.
336 *
337 * Global setting, indicate that the parser should keep all blanks
338 * nodes found in the content
339 * Activated by default, this is actually needed to have the parser
340 * conformant to the XML Recommendation, however the option is kept
341 * for some applications since this was libxml1 default behaviour.
342 */
343int xmlKeepBlanksDefaultValue = 1;
344static int xmlKeepBlanksDefaultValueThrDef = 1;
345/**
346 * xmlSubstituteEntitiesDefaultValue:
347 *
348 * DEPRECATED: Use the modern options API with XML_PARSE_NOENT.
349 *
350 * Global setting, indicate that the parser should not generate entity
351 * references but replace them with the actual content of the entity
352 * Disabled by default, this should be activated when using XPath since
353 * the XPath data model requires entities replacement and the XPath
354 * engine does not handle entities references transparently.
355 */
356int xmlSubstituteEntitiesDefaultValue = 0;
357static int xmlSubstituteEntitiesDefaultValueThrDef = 0;
358
359/**
360 * xmlRegisterNodeDefaultValue:
361 *
362 * DEPRECATED: Don't use
363 */
364xmlRegisterNodeFunc xmlRegisterNodeDefaultValue = NULL;
365static xmlRegisterNodeFunc xmlRegisterNodeDefaultValueThrDef = NULL;
366
367/**
368 * xmlDeregisterNodeDefaultValue:
369 *
370 * DEPRECATED: Don't use
371 */
372xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue = NULL;
373static xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValueThrDef = NULL;
374
375/**
376 * xmlParserInputBufferCreateFilenameValue:
377 *
378 * DEPRECATED: Don't use
379 */
380xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue = NULL;
381static xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValueThrDef = NULL;
382
383/**
384 * xmlOutputBufferCreateFilenameValue:
385 *
386 * DEPRECATED: Don't use
387 */
388xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue = NULL;
389static xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValueThrDef = NULL;
390
391/**
392 * xmlGenericError:
393 *
394 * Global setting: function used for generic error callbacks
395 */
396xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc;
397static xmlGenericErrorFunc xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
398/**
399 * xmlStructuredError:
400 *
401 * Global setting: function used for structured error callbacks
402 */
403xmlStructuredErrorFunc xmlStructuredError = NULL;
404static xmlStructuredErrorFunc xmlStructuredErrorThrDef = NULL;
405/**
406 * xmlGenericErrorContext:
407 *
408 * Global setting passed to generic error callbacks
409 */
410void *xmlGenericErrorContext = NULL;
411static void *xmlGenericErrorContextThrDef = NULL;
412/**
413 * xmlStructuredErrorContext:
414 *
415 * Global setting passed to structured error callbacks
416 */
417void *xmlStructuredErrorContext = NULL;
418static void *xmlStructuredErrorContextThrDef = NULL;
419xmlError xmlLastError;
420
421#ifdef LIBXML_OUTPUT_ENABLED
422/*
423 * output defaults
424 */
425/**
426 * xmlIndentTreeOutput:
427 *
428 * Global setting, asking the serializer to indent the output tree by default
429 * Enabled by default
430 */
431int xmlIndentTreeOutput = 1;
432static int xmlIndentTreeOutputThrDef = 1;
433
434/**
435 * xmlTreeIndentString:
436 *
437 * The string used to do one-level indent. By default is equal to " " (two spaces)
438 */
439const char *xmlTreeIndentString = " ";
440static const char *xmlTreeIndentStringThrDef = " ";
441
442/**
443 * xmlSaveNoEmptyTags:
444 *
445 * Global setting, asking the serializer to not output empty tags
446 * as <empty/> but <empty></empty>. those two forms are indistinguishable
447 * once parsed.
448 * Disabled by default
449 */
450int xmlSaveNoEmptyTags = 0;
451static int xmlSaveNoEmptyTagsThrDef = 0;
452#endif /* LIBXML_OUTPUT_ENABLED */
453
454#ifdef LIBXML_SAX1_ENABLED
455/**
456 * xmlDefaultSAXHandler:
457 *
458 * DEPRECATED: This handler is unused and will be removed from future
459 * versions.
460 *
461 * Default SAX version1 handler for XML, builds the DOM tree
462 */
463xmlSAXHandlerV1 xmlDefaultSAXHandler = {
464 xmlSAX2InternalSubset,
465 xmlSAX2IsStandalone,
466 xmlSAX2HasInternalSubset,
467 xmlSAX2HasExternalSubset,
468 xmlSAX2ResolveEntity,
469 xmlSAX2GetEntity,
470 xmlSAX2EntityDecl,
471 xmlSAX2NotationDecl,
472 xmlSAX2AttributeDecl,
473 xmlSAX2ElementDecl,
474 xmlSAX2UnparsedEntityDecl,
475 xmlSAX2SetDocumentLocator,
476 xmlSAX2StartDocument,
477 xmlSAX2EndDocument,
478 xmlSAX2StartElement,
479 xmlSAX2EndElement,
480 xmlSAX2Reference,
481 xmlSAX2Characters,
482 xmlSAX2Characters,
483 xmlSAX2ProcessingInstruction,
484 xmlSAX2Comment,
485 xmlParserWarning,
486 xmlParserError,
487 xmlParserError,
488 xmlSAX2GetParameterEntity,
489 xmlSAX2CDataBlock,
490 xmlSAX2ExternalSubset,
491 1,
492};
493#endif /* LIBXML_SAX1_ENABLED */
494
495/**
496 * xmlDefaultSAXLocator:
497 *
498 * DEPRECATED: Don't use
499 *
500 * The default SAX Locator
501 * { getPublicId, getSystemId, getLineNumber, getColumnNumber}
502 */
503xmlSAXLocator xmlDefaultSAXLocator = {
504 xmlSAX2GetPublicId,
505 xmlSAX2GetSystemId,
506 xmlSAX2GetLineNumber,
507 xmlSAX2GetColumnNumber
508};
509
510#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_SAX1_ENABLED)
511/**
512 * htmlDefaultSAXHandler:
513 *
514 * DEPRECATED: This handler is unused and will be removed from future
515 * versions.
516 *
517 * Default old SAX v1 handler for HTML, builds the DOM tree
518 */
519xmlSAXHandlerV1 htmlDefaultSAXHandler = {
520 xmlSAX2InternalSubset,
521 NULL,
522 NULL,
523 NULL,
524 NULL,
525 xmlSAX2GetEntity,
526 NULL,
527 NULL,
528 NULL,
529 NULL,
530 NULL,
531 xmlSAX2SetDocumentLocator,
532 xmlSAX2StartDocument,
533 xmlSAX2EndDocument,
534 xmlSAX2StartElement,
535 xmlSAX2EndElement,
536 NULL,
537 xmlSAX2Characters,
538 xmlSAX2IgnorableWhitespace,
539 xmlSAX2ProcessingInstruction,
540 xmlSAX2Comment,
541 xmlParserWarning,
542 xmlParserError,
543 xmlParserError,
544 NULL,
545 xmlSAX2CDataBlock,
546 NULL,
547 1,
548};
549#endif /* LIBXML_HTML_ENABLED */
550
551/************************************************************************
552 * *
553 * Per thread global state handling *
554 * *
555 ************************************************************************/
556
557/**
558 * xmlInitGlobals:
559 *
560 * DEPRECATED: Alias for xmlInitParser.
561 */
562void xmlInitGlobals(void) {
563 xmlInitParser();
564}
565
566/**
567 * xmlInitGlobalsInternal:
568 *
569 * Additional initialisation for multi-threading
570 */
571void xmlInitGlobalsInternal(void) {
572 xmlInitMutex(&xmlThrDefMutex);
573
574#ifdef HAVE_POSIX_THREADS
575#ifdef XML_PTHREAD_WEAK
576 if (libxml_is_threaded == -1)
577 libxml_is_threaded =
578 (pthread_getspecific != NULL) &&
579 (pthread_setspecific != NULL) &&
580 (pthread_key_create != NULL) &&
581 (pthread_key_delete != NULL) &&
582 /*
583 * pthread_equal can be inline, resuting in -Waddress warnings.
584 * Let's assume it's available if all the other functions are.
585 */
586 /* (pthread_equal != NULL) && */
587 (pthread_self != NULL);
588 if (libxml_is_threaded == 0)
589 return;
590#endif /* XML_PTHREAD_WEAK */
591 pthread_key_create(&globalkey, xmlFreeGlobalState);
592 mainthread = pthread_self();
593#elif defined(HAVE_WIN32_THREADS)
594#ifndef USE_TLS
595 globalkey = TlsAlloc();
596#endif
597 mainthread = GetCurrentThreadId();
598#endif
599}
600
601/**
602 * xmlCleanupGlobals:
603 *
604 * DEPRECATED: This function is a no-op. Call xmlCleanupParser
605 * to free global state but see the warnings there. xmlCleanupParser
606 * should be only called once at program exit. In most cases, you don't
607 * have call cleanup functions at all.
608 */
609void xmlCleanupGlobals(void) {
610}
611
612/**
613 * xmlCleanupGlobalsInternal:
614 *
615 * Additional cleanup for multi-threading
616 */
617void xmlCleanupGlobalsInternal(void) {
618 xmlResetError(&xmlLastError);
619
620 xmlCleanupMutex(&xmlThrDefMutex);
621
622#ifdef HAVE_POSIX_THREADS
623#ifdef XML_PTHREAD_WEAK
624 if (libxml_is_threaded == 0)
625 return;
626#endif /* XML_PTHREAD_WEAK */
627 pthread_key_delete(globalkey);
628#elif defined(HAVE_WIN32_THREADS)
629#ifndef USE_TLS
630 if (globalkey != TLS_OUT_OF_INDEXES) {
631 TlsFree(globalkey);
632 globalkey = TLS_OUT_OF_INDEXES;
633 }
634#endif
635#endif
636
637 parserInitialized = 0;
638}
639
640/**
641 * xmlInitializeGlobalState:
642 * @gs: a pointer to a newly allocated global state
643 *
644 * DEPRECATED: No-op.
645 */
646void
647xmlInitializeGlobalState(xmlGlobalStatePtr gs ATTRIBUTE_UNUSED)
648{
649}
650
651/**
652 * xmlGetGlobalState:
653 *
654 * DEPRECATED
655 *
656 * Returns NULL.
657 */
658xmlGlobalStatePtr
659xmlGetGlobalState(void)
660{
661 return(NULL);
662}
663
664static int
665xmlIsMainThreadInternal(void) {
666 if (parserInitialized == 0) {
667 xmlInitParser();
668 parserInitialized = 1;
669 }
670
671#ifdef HAVE_POSIX_THREADS
672#ifdef XML_PTHREAD_WEAK
673 if (libxml_is_threaded == 0)
674 return (1);
675#endif
676 return (pthread_equal(mainthread, pthread_self()));
677#elif defined HAVE_WIN32_THREADS
678 return (mainthread == GetCurrentThreadId());
679#else
680 return (1);
681#endif
682}
683
684/**
685 * xmlIsMainThread:
686 *
687 * DEPRECATED: Internal function, do not use.
688 *
689 * Check whether the current thread is the main thread.
690 *
691 * Returns 1 if the current thread is the main thread, 0 otherwise
692 */
693int
694xmlIsMainThread(void) {
695 return(xmlIsMainThreadInternal());
696}
697
698#ifdef LIBXML_THREAD_ENABLED
699
700static void
701xmlFreeGlobalState(void *state)
702{
703 xmlGlobalState *gs = (xmlGlobalState *) state;
704
705 /*
706 * Free any memory allocated in the thread's xmlLastError. If it
707 * weren't for this indirect allocation, we wouldn't need
708 * a destructor with thread-local storage at all!
709 *
710 * It would be nice if we could make xmlLastError a special error
711 * type which uses statically allocated, fixed-size buffers.
712 * But the xmlError struct is fully public and widely used,
713 * so changes are dangerous.
714 */
715 xmlResetError(&(gs->gs_xmlLastError));
716#ifndef USE_TLS
717 free(state);
718#endif
719}
720
721#if defined(HAVE_WIN32_THREADS) && \
722 defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
723static void WINAPI
724xmlGlobalStateDtor(void *ctxt, unsigned char timedOut ATTRIBUTE_UNUSED) {
725 xmlGlobalStatePtr gs = ctxt;
726
727 UnregisterWait(gs->waitHandle);
728 CloseHandle(gs->threadHandle);
729 xmlFreeGlobalState(gs);
730}
731
732static int
733xmlRegisterGlobalStateDtor(xmlGlobalState *gs) {
734 void *processHandle = GetCurrentProcess();
735 void *threadHandle;
736 void *waitHandle;
737
738 if (DuplicateHandle(processHandle, GetCurrentThread(), processHandle,
739 &threadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) {
740 return(-1);
741 }
742
743 if (RegisterWaitForSingleObject(&waitHandle, threadHandle,
744 xmlGlobalStateDtor, gs, INFINITE, WT_EXECUTEONLYONCE) == 0) {
745 CloseHandle(threadHandle);
746 return(-1);
747 }
748
749 gs->threadHandle = threadHandle;
750 gs->waitHandle = waitHandle;
751 return(0);
752}
753#endif /* LIBXML_STATIC */
754
755static void
756xmlInitGlobalState(xmlGlobalStatePtr gs) {
757 xmlMutexLock(&xmlThrDefMutex);
758
759#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_LEGACY_ENABLED) && defined(LIBXML_SAX1_ENABLED)
760 inithtmlDefaultSAXHandler(&gs->gs_htmlDefaultSAXHandler);
761#endif
762
763 gs->gs_oldXMLWDcompatibility = 0;
764 gs->gs_xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
765 gs->gs_xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
766#if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_LEGACY_ENABLED)
767 initxmlDefaultSAXHandler(&gs->gs_xmlDefaultSAXHandler, 1);
768#endif /* LIBXML_SAX1_ENABLED */
769 gs->gs_xmlDefaultSAXLocator.getPublicId = xmlSAX2GetPublicId;
770 gs->gs_xmlDefaultSAXLocator.getSystemId = xmlSAX2GetSystemId;
771 gs->gs_xmlDefaultSAXLocator.getLineNumber = xmlSAX2GetLineNumber;
772 gs->gs_xmlDefaultSAXLocator.getColumnNumber = xmlSAX2GetColumnNumber;
773 gs->gs_xmlDoValidityCheckingDefaultValue =
774 xmlDoValidityCheckingDefaultValueThrDef;
775#ifdef LIBXML_THREAD_ALLOC_ENABLED
776#ifdef DEBUG_MEMORY_LOCATION
777 gs->gs_xmlFree = xmlMemFree;
778 gs->gs_xmlMalloc = xmlMemMalloc;
779 gs->gs_xmlMallocAtomic = xmlMemMalloc;
780 gs->gs_xmlRealloc = xmlMemRealloc;
781 gs->gs_xmlMemStrdup = xmlMemoryStrdup;
782#else
783 gs->gs_xmlFree = free;
784 gs->gs_xmlMalloc = malloc;
785 gs->gs_xmlMallocAtomic = malloc;
786 gs->gs_xmlRealloc = realloc;
787 gs->gs_xmlMemStrdup = xmlPosixStrdup;
788#endif
789#endif
790 gs->gs_xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
791#ifdef LIBXML_OUTPUT_ENABLED
792 gs->gs_xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
793 gs->gs_xmlTreeIndentString = xmlTreeIndentStringThrDef;
794 gs->gs_xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
795#endif
796 gs->gs_xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
797 gs->gs_xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
798 gs->gs_xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
799 gs->gs_xmlParserDebugEntities = xmlParserDebugEntitiesThrDef;
800 gs->gs_xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
801 gs->gs_xmlSubstituteEntitiesDefaultValue =
802 xmlSubstituteEntitiesDefaultValueThrDef;
803
804 gs->gs_xmlGenericError = xmlGenericErrorThrDef;
805 gs->gs_xmlStructuredError = xmlStructuredErrorThrDef;
806 gs->gs_xmlGenericErrorContext = xmlGenericErrorContextThrDef;
807 gs->gs_xmlStructuredErrorContext = xmlStructuredErrorContextThrDef;
808 gs->gs_xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
809 gs->gs_xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
810
811 gs->gs_xmlParserInputBufferCreateFilenameValue =
812 xmlParserInputBufferCreateFilenameValueThrDef;
813 gs->gs_xmlOutputBufferCreateFilenameValue =
814 xmlOutputBufferCreateFilenameValueThrDef;
815 memset(&gs->gs_xmlLastError, 0, sizeof(xmlError));
816
817 xmlMutexUnlock(&xmlThrDefMutex);
818
819#ifdef HAVE_POSIX_THREADS
820 pthread_setspecific(globalkey, gs);
821#elif defined HAVE_WIN32_THREADS
822#ifndef USE_TLS
823 TlsSetValue(globalkey, gs);
824#endif
825#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
826 xmlRegisterGlobalStateDtor(gs);
827#endif
828#endif
829
830 gs->initialized = 1;
831}
832
833#ifndef USE_TLS
834/**
835 * xmlNewGlobalState:
836 *
837 * xmlNewGlobalState() allocates a global state. This structure is used to
838 * hold all data for use by a thread when supporting backwards compatibility
839 * of libxml2 to pre-thread-safe behaviour.
840 *
841 * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
842 */
843static xmlGlobalStatePtr
844xmlNewGlobalState(int allowFailure)
845{
846 xmlGlobalState *gs;
847
848 gs = malloc(sizeof(xmlGlobalState));
849 if (gs == NULL) {
850 if (allowFailure)
851 return(NULL);
852
853 /*
854 * If an application didn't call xmlCheckThreadLocalStorage to make
855 * sure that global state could be allocated, it's too late to
856 * handle the error.
857 */
858 fprintf(stderr, "libxml2: Failed to allocate globals for thread\n"
859 "libxml2: See xmlCheckThreadLocalStorage\n");
860 abort();
861 }
862
863 memset(gs, 0, sizeof(xmlGlobalState));
864 xmlInitGlobalState(gs);
865 return (gs);
866}
867#endif
868
869static xmlGlobalStatePtr
870xmlGetThreadLocalStorage(int allowFailure) {
871 xmlGlobalState *gs;
872
873 (void) allowFailure;
874
875#ifdef USE_TLS
876 gs = &globalState;
877 if (gs->initialized == 0)
878 xmlInitGlobalState(gs);
879#elif defined(HAVE_POSIX_THREADS)
880 gs = (xmlGlobalState *) pthread_getspecific(globalkey);
881 if (gs == NULL)
882 gs = xmlNewGlobalState(allowFailure);
883#elif defined(HAVE_WIN32_THREADS)
884 gs = (xmlGlobalState *) TlsGetValue(globalkey);
885 if (gs == NULL)
886 gs = xmlNewGlobalState(allowFailure);
887#else
888 gs = NULL;
889#endif
890
891 return(gs);
892}
893
894/* Define thread-local storage accessors with macro magic */
895
896#define XML_DEFINE_GLOBAL_WRAPPER(name, type, attrs) \
897 type *__##name(void) { \
898 if (IS_MAIN_THREAD) \
899 return (&name); \
900 else \
901 return (&xmlGetThreadLocalStorage(0)->gs_##name); \
902 }
903
904#define XML_OP XML_DEFINE_GLOBAL_WRAPPER
905XML_GLOBALS_ALLOC
906XML_GLOBALS_ERROR
907XML_GLOBALS_HTML
908XML_GLOBALS_IO
909XML_GLOBALS_PARSER
910XML_GLOBALS_TREE
911#undef XML_OP
912
913/* For backward compatibility */
914
915const char *const *
916__xmlParserVersion(void) {
917 return &xmlParserVersion;
918}
919
920#endif /* LIBXML_THREAD_ENABLED */
921
922/**
923 * xmlCheckThreadLocalStorage:
924 *
925 * Check whether thread-local storage could be allocated.
926 *
927 * In cross-platform code running in multithreaded environments, this
928 * function should be called once in each thread before calling other
929 * library functions to make sure that thread-local storage was
930 * allocated properly.
931 *
932 * Returns 0 on success or -1 if a memory allocation failed. A failed
933 * allocation signals a typically fatal and irrecoverable out-of-memory
934 * situation. Don't call any library functions in this case.
935 *
936 * This function never fails if the library is compiled with support
937 * for thread-local storage.
938 *
939 * This function never fails for the "main" thread which is the first
940 * thread calling xmlInitParser.
941 *
942 * Available since v2.12.0.
943 */
944int
945xmlCheckThreadLocalStorage(void) {
946#if defined(LIBXML_THREAD_ENABLED) && !defined(USE_TLS)
947 if ((!xmlIsMainThreadInternal()) && (xmlGetThreadLocalStorage(1) == NULL))
948 return(-1);
949#endif
950 return(0);
951}
952
953/**
954 * DllMain:
955 * @hinstDLL: handle to DLL instance
956 * @fdwReason: Reason code for entry
957 * @lpvReserved: generic pointer (depends upon reason code)
958 *
959 * Entry point for Windows library. It is being used to free thread-specific
960 * storage.
961 *
962 * Returns TRUE always
963 */
964#if defined(HAVE_WIN32_THREADS) && \
965 (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
966#if defined(LIBXML_STATIC_FOR_DLL)
967int
968xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
969 ATTRIBUTE_UNUSED void *lpvReserved)
970#else
971/* declare to avoid "no previous prototype for 'DllMain'" warning */
972/* Note that we do NOT want to include this function declaration in
973 a public header because it's meant to be called by Windows itself,
974 not a program that uses this library. This also has to be exported. */
975
976XMLPUBFUN BOOL WINAPI
977DllMain (HINSTANCE hinstDLL,
978 DWORD fdwReason,
979 LPVOID lpvReserved);
980
981BOOL WINAPI
982DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
983 ATTRIBUTE_UNUSED LPVOID lpvReserved)
984#endif
985{
986 switch (fdwReason) {
987 case DLL_THREAD_DETACH:
988#ifdef USE_TLS
989 xmlFreeGlobalState(&globalState);
990#else
991 if (globalkey != TLS_OUT_OF_INDEXES) {
992 xmlGlobalState *globalval;
993
994 globalval = (xmlGlobalState *) TlsGetValue(globalkey);
995 if (globalval) {
996 xmlFreeGlobalState(globalval);
997 TlsSetValue(globalkey, NULL);
998 }
999 }
1000#endif
1001 break;
1002 }
1003 return TRUE;
1004}
1005#endif
1006
1007void
1008xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
1009 xmlMutexLock(&xmlThrDefMutex);
1010 xmlGenericErrorContextThrDef = ctx;
1011 if (handler != NULL)
1012 xmlGenericErrorThrDef = handler;
1013 else
1014 xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
1015 xmlMutexUnlock(&xmlThrDefMutex);
1016}
1017
1018void
1019xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
1020 xmlMutexLock(&xmlThrDefMutex);
1021 xmlStructuredErrorContextThrDef = ctx;
1022 xmlStructuredErrorThrDef = handler;
1023 xmlMutexUnlock(&xmlThrDefMutex);
1024}
1025
1026xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) {
1027 xmlBufferAllocationScheme ret;
1028 xmlMutexLock(&xmlThrDefMutex);
1029 ret = xmlBufferAllocSchemeThrDef;
1030 xmlBufferAllocSchemeThrDef = v;
1031 xmlMutexUnlock(&xmlThrDefMutex);
1032 return ret;
1033}
1034
1035int xmlThrDefDefaultBufferSize(int v) {
1036 int ret;
1037 xmlMutexLock(&xmlThrDefMutex);
1038 ret = xmlDefaultBufferSizeThrDef;
1039 xmlDefaultBufferSizeThrDef = v;
1040 xmlMutexUnlock(&xmlThrDefMutex);
1041 return ret;
1042}
1043
1044int xmlThrDefDoValidityCheckingDefaultValue(int v) {
1045 int ret;
1046 xmlMutexLock(&xmlThrDefMutex);
1047 ret = xmlDoValidityCheckingDefaultValueThrDef;
1048 xmlDoValidityCheckingDefaultValueThrDef = v;
1049 xmlMutexUnlock(&xmlThrDefMutex);
1050 return ret;
1051}
1052
1053int xmlThrDefGetWarningsDefaultValue(int v) {
1054 int ret;
1055 xmlMutexLock(&xmlThrDefMutex);
1056 ret = xmlGetWarningsDefaultValueThrDef;
1057 xmlGetWarningsDefaultValueThrDef = v;
1058 xmlMutexUnlock(&xmlThrDefMutex);
1059 return ret;
1060}
1061
1062#ifdef LIBXML_OUTPUT_ENABLED
1063int xmlThrDefIndentTreeOutput(int v) {
1064 int ret;
1065 xmlMutexLock(&xmlThrDefMutex);
1066 ret = xmlIndentTreeOutputThrDef;
1067 xmlIndentTreeOutputThrDef = v;
1068 xmlMutexUnlock(&xmlThrDefMutex);
1069 return ret;
1070}
1071
1072const char * xmlThrDefTreeIndentString(const char * v) {
1073 const char * ret;
1074 xmlMutexLock(&xmlThrDefMutex);
1075 ret = xmlTreeIndentStringThrDef;
1076 xmlTreeIndentStringThrDef = v;
1077 xmlMutexUnlock(&xmlThrDefMutex);
1078 return ret;
1079}
1080
1081int xmlThrDefSaveNoEmptyTags(int v) {
1082 int ret;
1083 xmlMutexLock(&xmlThrDefMutex);
1084 ret = xmlSaveNoEmptyTagsThrDef;
1085 xmlSaveNoEmptyTagsThrDef = v;
1086 xmlMutexUnlock(&xmlThrDefMutex);
1087 return ret;
1088}
1089#endif
1090
1091int xmlThrDefKeepBlanksDefaultValue(int v) {
1092 int ret;
1093 xmlMutexLock(&xmlThrDefMutex);
1094 ret = xmlKeepBlanksDefaultValueThrDef;
1095 xmlKeepBlanksDefaultValueThrDef = v;
1096 xmlMutexUnlock(&xmlThrDefMutex);
1097 return ret;
1098}
1099
1100int xmlThrDefLineNumbersDefaultValue(int v) {
1101 int ret;
1102 xmlMutexLock(&xmlThrDefMutex);
1103 ret = xmlLineNumbersDefaultValueThrDef;
1104 xmlLineNumbersDefaultValueThrDef = v;
1105 xmlMutexUnlock(&xmlThrDefMutex);
1106 return ret;
1107}
1108
1109int xmlThrDefLoadExtDtdDefaultValue(int v) {
1110 int ret;
1111 xmlMutexLock(&xmlThrDefMutex);
1112 ret = xmlLoadExtDtdDefaultValueThrDef;
1113 xmlLoadExtDtdDefaultValueThrDef = v;
1114 xmlMutexUnlock(&xmlThrDefMutex);
1115 return ret;
1116}
1117
1118int xmlThrDefParserDebugEntities(int v) {
1119 int ret;
1120 xmlMutexLock(&xmlThrDefMutex);
1121 ret = xmlParserDebugEntitiesThrDef;
1122 xmlParserDebugEntitiesThrDef = v;
1123 xmlMutexUnlock(&xmlThrDefMutex);
1124 return ret;
1125}
1126
1127int xmlThrDefPedanticParserDefaultValue(int v) {
1128 int ret;
1129 xmlMutexLock(&xmlThrDefMutex);
1130 ret = xmlPedanticParserDefaultValueThrDef;
1131 xmlPedanticParserDefaultValueThrDef = v;
1132 xmlMutexUnlock(&xmlThrDefMutex);
1133 return ret;
1134}
1135
1136int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
1137 int ret;
1138 xmlMutexLock(&xmlThrDefMutex);
1139 ret = xmlSubstituteEntitiesDefaultValueThrDef;
1140 xmlSubstituteEntitiesDefaultValueThrDef = v;
1141 xmlMutexUnlock(&xmlThrDefMutex);
1142 return ret;
1143}
1144
1145xmlRegisterNodeFunc
1146xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)
1147{
1148 xmlRegisterNodeFunc old;
1149
1150 xmlMutexLock(&xmlThrDefMutex);
1151 old = xmlRegisterNodeDefaultValueThrDef;
1152
1153 __xmlRegisterCallbacks = 1;
1154 xmlRegisterNodeDefaultValueThrDef = func;
1155 xmlMutexUnlock(&xmlThrDefMutex);
1156
1157 return(old);
1158}
1159
1160xmlDeregisterNodeFunc
1161xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
1162{
1163 xmlDeregisterNodeFunc old;
1164
1165 xmlMutexLock(&xmlThrDefMutex);
1166 old = xmlDeregisterNodeDefaultValueThrDef;
1167
1168 __xmlRegisterCallbacks = 1;
1169 xmlDeregisterNodeDefaultValueThrDef = func;
1170 xmlMutexUnlock(&xmlThrDefMutex);
1171
1172 return(old);
1173}
1174
1175xmlParserInputBufferCreateFilenameFunc
1176xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
1177{
1178 xmlParserInputBufferCreateFilenameFunc old;
1179
1180 xmlMutexLock(&xmlThrDefMutex);
1181 old = xmlParserInputBufferCreateFilenameValueThrDef;
1182 if (old == NULL) {
1183 old = __xmlParserInputBufferCreateFilename;
1184 }
1185
1186 xmlParserInputBufferCreateFilenameValueThrDef = func;
1187 xmlMutexUnlock(&xmlThrDefMutex);
1188
1189 return(old);
1190}
1191
1192xmlOutputBufferCreateFilenameFunc
1193xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
1194{
1195 xmlOutputBufferCreateFilenameFunc old;
1196
1197 xmlMutexLock(&xmlThrDefMutex);
1198 old = xmlOutputBufferCreateFilenameValueThrDef;
1199#ifdef LIBXML_OUTPUT_ENABLED
1200 if (old == NULL) {
1201 old = __xmlOutputBufferCreateFilename;
1202 }
1203#endif
1204 xmlOutputBufferCreateFilenameValueThrDef = func;
1205 xmlMutexUnlock(&xmlThrDefMutex);
1206
1207 return(old);
1208}
1209
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use