DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=5238>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=5238

static void DOMStringTerminate() is not atomic and can crash rarely

           Summary: static void DOMStringTerminate() is not atomic and can
                    crash rarely
           Product: Xerces-C++
           Version: 1.5.1
          Platform: PC
        OS/Version: Windows NT/2K
            Status: NEW
          Severity: Critical
          Priority: Other
         Component: DOM
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


I observed crashes of Xerces-C 1.5.1. These crashes occurred only in highly 
multithreaded applications on a Dual-Pentium machine (2x750MHz Pentium III, 1GB 
RAM, Windows 2000 Server). On a single-processor machine I was not able to 
reproduce these crashes. 

The application concurrently parses small XMLs. The maximum number of threads 
concurrently parsing is 20, but the acutal number varies between 0 and 20. 

I tried to debug Xerces-C and found out why the application crashed:

The static function DOMStringTerminate() is only called by 
DOMStringHandle::operator delete. The comments there say that "This will 
generally only happen on PlatFormUtils::Terminate(), since any use of the DOM 
will cache some commonly used DOMStrings forever (until Terminate)." But this 
is in fact not the case. 

In a simple application which executes the following steps
1. Initialize
2. Parse an XML
3. Parse another XML
4. Terminate

DOMStringTerminate is called after step 2 AND after step 3. In a multithreaded 
application this can cause the application to crash. The reasons are the 
following:

1. DOMStringTerminate() deletes the synchronization mutex and sets its value to 
NULL:
        delete DOMStringHandleMutex;    //  Delete the synchronization mutex,
        DOMStringHandleMutex = 0;

2. A different thread might access this mutex using XMLMutex& 
DOMStringHandle::getMutex() which is called from DOMStringHandle::operator new 
or DOMStringHandle::operator delete.

XMLMutex& DOMStringHandle::getMutex()
{
    if (!DOMStringHandleMutex)
    {
        XMLMutex* tmpMutex = new XMLMutex;
        if (XMLPlatformUtils::compareAndSwap((void**)&DOMStringHandleMutex, 
tmpMutex, 0))
        {
            // Someone beat us to it, so let's clean up ours
            delete tmpMutex;
        }
    }

    return *DOMStringHandleMutex;
}

3. Now let a multithreaded process execute the following code:

a) Thread 1: enter DOMStringTerminate()
b) Thread 1: call delete DOMStringHandleMutex;
c) Thread 2: enter DOMStringHandle::getMutex()
d) Thread 2: calling if (!DOMStringHandleMutex) yields FALSE als 
DOMStringHandleMutex is still != NULL, though already deleted
e) Thread 2: call return *DOMStringHandleMutex;
f) Thread 1: call DOMStringHandleMutex = 0;

In this case DOMStringHandleMutex is used by Thread 2 although it is 
concurrently deleted by Thread 1. This is due to the fact that 
DOMStringTerminate() is not atomic, but it should be. DOMStringHandle::getMutex 
is atomic. 

While debugging I found out that the scenario a) to f) in fact occurs, 
consequently Thread 2 crashes when trying to use the just deleted 
DOMStringHandleMutex.

Please contact me directly when more questions occur. I hope I can help you 
then.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to