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
This commit is contained in:
rfm 2006-02-27 16:54:36 +00:00
parent 7d3f438da0
commit 988a86dda1
2 changed files with 28 additions and 46 deletions

View file

@ -1,3 +1,13 @@
2006-02-27 Richard Frith-Macdonald <rfm@gnu.org>
* 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 <rfm@gnu.org> 2006-02-27 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSString.h: Correct return type for * Headers/Foundation/NSString.h: Correct return type for

View file

@ -166,8 +166,8 @@ setupCache()
} }
static xmlParserInputPtr static xmlParserInputPtr
loadEntityFunction(const unsigned char *url, const unsigned char *eid, loadEntityFunction(void *ctx,
xmlParserCtxtPtr ctxt); const unsigned char *eid, const unsigned char *url);
@interface GSXPathObject(Private) @interface GSXPathObject(Private)
+ (id) _newWithNativePointer: (xmlXPathObject *)lib + (id) _newWithNativePointer: (xmlXPathObject *)lib
@ -1609,8 +1609,6 @@ static NSMapTable *nodeNames = 0;
*/ */
@implementation GSXMLParser @implementation GSXMLParser
static NSHashTable *warnings = 0;
static NSString *endMarker = @"At end of incremental parse"; static NSString *endMarker = @"At end of incremental parse";
+ (void) initialize + (void) initialize
@ -1622,7 +1620,6 @@ static NSString *endMarker = @"At end of incremental parse";
beenHere = YES; beenHere = YES;
if (cacheDone == NO) if (cacheDone == NO)
setupCache(); setupCache();
warnings = NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
} }
} }
@ -1864,7 +1861,6 @@ static NSString *endMarker = @"At end of incremental parse";
- (void) dealloc - (void) dealloc
{ {
NSHashRemove(warnings, self);
RELEASE(messages); RELEASE(messages);
RELEASE(src); RELEASE(src);
RELEASE(saxHandler); RELEASE(saxHandler);
@ -1912,20 +1908,17 @@ static NSString *endMarker = @"At end of incremental parse";
*/ */
- (BOOL) getWarnings: (BOOL)yesno - (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); ((xmlParserCtxtPtr)lib)->vctxt.warning = 0;
}
else if (yesno == NO && old == YES)
{
NSHashRemove(warnings, self);
} }
return old; return old;
} }
@ -2305,6 +2298,11 @@ static NSString *endMarker = @"At end of incremental parse";
* the GSSAXHandler to use in our SAX C Functions. * the GSSAXHandler to use in our SAX C Functions.
*/ */
((xmlParserCtxtPtr)lib)->_private = saxHandler; ((xmlParserCtxtPtr)lib)->_private = saxHandler;
/*
* Set the entity loading function for this parser to be our one.
*/
((xmlParserCtxtPtr)lib)->sax->resolveEntity = loadEntityFunction;
} }
return YES; return YES;
} }
@ -2317,38 +2315,11 @@ static NSString *endMarker = @"At end of incremental parse";
// nil data allowed // nil data allowed
- (void) _parseChunk: (NSData*)data - (void) _parseChunk: (NSData*)data
{ {
xmlExternalEntityLoader oldLoader;
int oldWarnings;
if (lib == NULL || ((xmlParserCtxtPtr)lib)->disableSAX != 0) if (lib == NULL || ((xmlParserCtxtPtr)lib)->disableSAX != 0)
{ {
return; // Parsing impossible or disabled. return; // Parsing impossible or disabled.
} }
xmlParseChunk(lib, [data bytes], [data length], data == nil);
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
} }
@end @end
@ -2436,8 +2407,8 @@ static NSString *endMarker = @"At end of incremental parse";
#define HANDLER ((GSSAXHandler*)(((xmlParserCtxtPtr)ctx)->_private)) #define HANDLER ((GSSAXHandler*)(((xmlParserCtxtPtr)ctx)->_private))
static xmlParserInputPtr static xmlParserInputPtr
loadEntityFunction(const unsigned char *url, const unsigned char *eid, loadEntityFunction(void *ctx,
xmlParserCtxtPtr ctx) const unsigned char *eid, const unsigned char *url)
{ {
extern xmlParserInputPtr xmlNewInputFromFile(); extern xmlParserInputPtr xmlNewInputFromFile();
NSString *file; NSString *file;
@ -2596,7 +2567,7 @@ loadEntityFunction(const unsigned char *url, const unsigned char *eid,
#else #else
path = [file fileSystemRepresentation]; path = [file fileSystemRepresentation];
#endif #endif
ret = xmlNewInputFromFile(ctx, path); ret = xmlNewInputFromFile((xmlParserCtxtPtr)ctx, path);
} }
else else
{ {
@ -2605,6 +2576,7 @@ loadEntityFunction(const unsigned char *url, const unsigned char *eid,
return ret; return ret;
} }
#define TREEFUN(NAME,ARGS) ((HANDLER->isHtmlHandler == YES) ? (*(htmlDefaultSAXHandler.NAME))ARGS : (*(xmlDefaultSAXHandler.NAME))ARGS) #define TREEFUN(NAME,ARGS) ((HANDLER->isHtmlHandler == YES) ? (*(htmlDefaultSAXHandler.NAME))ARGS : (*(xmlDefaultSAXHandler.NAME))ARGS)
#define START(SELNAME, RET, ARGS) \ #define START(SELNAME, RET, ARGS) \
static SEL sel; \ static SEL sel; \