From 988a86dda16fb5143bada622f4b397264b3176d2 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 27 Feb 2006 16:54:36 +0000 Subject: [PATCH] Add attempts at thread safety as long as different parsers are kept in different threads. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@22577 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 10 +++++++ Source/Additions/GSXML.m | 64 +++++++++++----------------------------- 2 files changed, 28 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index a3714a934..093db83e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2006-02-27 Richard Frith-Macdonald + + * Source/Additions/GSXML.m: Helge spotted thread safety issues with + the code controlling warnings and the external entity loader. + Changed code to modify internals of the parser context and SAX + context to set the values in there directly rather than using the + global setter mechanism (strangely recommended in the libxml2 docs), + so that all setup is made to the individual parser and should not + effect other parsers in other threads. + 2006-02-27 Richard Frith-Macdonald * Headers/Foundation/NSString.h: Correct return type for diff --git a/Source/Additions/GSXML.m b/Source/Additions/GSXML.m index bdb6ca5e0..77c82ee85 100644 --- a/Source/Additions/GSXML.m +++ b/Source/Additions/GSXML.m @@ -166,8 +166,8 @@ setupCache() } static xmlParserInputPtr -loadEntityFunction(const unsigned char *url, const unsigned char *eid, - xmlParserCtxtPtr ctxt); +loadEntityFunction(void *ctx, + const unsigned char *eid, const unsigned char *url); @interface GSXPathObject(Private) + (id) _newWithNativePointer: (xmlXPathObject *)lib @@ -1609,8 +1609,6 @@ static NSMapTable *nodeNames = 0; */ @implementation GSXMLParser -static NSHashTable *warnings = 0; - static NSString *endMarker = @"At end of incremental parse"; + (void) initialize @@ -1622,7 +1620,6 @@ static NSString *endMarker = @"At end of incremental parse"; beenHere = YES; if (cacheDone == NO) setupCache(); - warnings = NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0); } } @@ -1864,7 +1861,6 @@ static NSString *endMarker = @"At end of incremental parse"; - (void) dealloc { - NSHashRemove(warnings, self); RELEASE(messages); RELEASE(src); RELEASE(saxHandler); @@ -1912,20 +1908,17 @@ static NSString *endMarker = @"At end of incremental parse"; */ - (BOOL) getWarnings: (BOOL)yesno { - BOOL old = YES; + BOOL old = (((xmlParserCtxtPtr)lib)->vctxt.warning) ? YES : NO; - if (NSHashGet(warnings, self) == nil) + if (yesno == YES) { - old = NO; + ((xmlParserCtxtPtr)lib)->vctxt.warning = xmlParserValidityWarning; } - if (yesno == YES && old == NO) + else { - NSHashInsert(warnings, self); - } - else if (yesno == NO && old == YES) - { - NSHashRemove(warnings, self); + ((xmlParserCtxtPtr)lib)->vctxt.warning = 0; } + return old; } @@ -2305,6 +2298,11 @@ static NSString *endMarker = @"At end of incremental parse"; * the GSSAXHandler to use in our SAX C Functions. */ ((xmlParserCtxtPtr)lib)->_private = saxHandler; + + /* + * Set the entity loading function for this parser to be our one. + */ + ((xmlParserCtxtPtr)lib)->sax->resolveEntity = loadEntityFunction; } return YES; } @@ -2317,38 +2315,11 @@ static NSString *endMarker = @"At end of incremental parse"; // nil data allowed - (void) _parseChunk: (NSData*)data { - xmlExternalEntityLoader oldLoader; - int oldWarnings; - if (lib == NULL || ((xmlParserCtxtPtr)lib)->disableSAX != 0) { return; // Parsing impossible or disabled. } - - oldLoader = xmlGetExternalEntityLoader(); - oldWarnings = xmlGetWarningsDefaultValue; - NS_DURING - { - if (NSHashGet(warnings, self) == nil) - { - xmlGetWarningsDefaultValue = 0; - } - else - { - xmlGetWarningsDefaultValue = 1; - } - xmlSetExternalEntityLoader((xmlExternalEntityLoader)loadEntityFunction); - xmlParseChunk(lib, [data bytes], [data length], data == nil); - xmlSetExternalEntityLoader(oldLoader); - xmlGetWarningsDefaultValue = oldWarnings; - } - NS_HANDLER - { - xmlSetExternalEntityLoader(oldLoader); - xmlGetWarningsDefaultValue = oldWarnings; - [localException raise]; - } - NS_ENDHANDLER + xmlParseChunk(lib, [data bytes], [data length], data == nil); } @end @@ -2436,8 +2407,8 @@ static NSString *endMarker = @"At end of incremental parse"; #define HANDLER ((GSSAXHandler*)(((xmlParserCtxtPtr)ctx)->_private)) static xmlParserInputPtr -loadEntityFunction(const unsigned char *url, const unsigned char *eid, - xmlParserCtxtPtr ctx) +loadEntityFunction(void *ctx, + const unsigned char *eid, const unsigned char *url) { extern xmlParserInputPtr xmlNewInputFromFile(); NSString *file; @@ -2596,7 +2567,7 @@ loadEntityFunction(const unsigned char *url, const unsigned char *eid, #else path = [file fileSystemRepresentation]; #endif - ret = xmlNewInputFromFile(ctx, path); + ret = xmlNewInputFromFile((xmlParserCtxtPtr)ctx, path); } else { @@ -2605,6 +2576,7 @@ loadEntityFunction(const unsigned char *url, const unsigned char *eid, return ret; } + #define TREEFUN(NAME,ARGS) ((HANDLER->isHtmlHandler == YES) ? (*(htmlDefaultSAXHandler.NAME))ARGS : (*(xmlDefaultSAXHandler.NAME))ARGS) #define START(SELNAME, RET, ARGS) \ static SEL sel; \