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=5359>. 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=5359 Document reference counting fails in multi-threaded multi-processor environment Summary: Document reference counting fails in multi-threaded multi-processor environment Product: Xerces-C++ Version: 1.5.2 Platform: Sun OS/Version: Solaris Status: NEW Severity: Critical Priority: Other Component: DOM AssignedTo: [EMAIL PROTECTED] ReportedBy: [EMAIL PROTECTED] The error occurs infrequently, and so far never on a single-processor machine. It always occurs at the same point in the source code. The symptoms suggest that somehow the reference counter for a DocumentImpl object is corrupted so that the object is deleted while it is still in use. The error occurs in ParentNode::removeChild(): 387 //fix other ranges for change before deleting the node 388 if (getOwnerDocument() != null) { 389 typedef RefVectorOf<RangeImpl> RangeImpls; 390 RangeImpls* ranges = this->getOwnerDocument()->getRanges(); >> ranges != null here, which means the owner document has not yet been deleted 391 if (ranges != null) { 392 unsigned int sz = ranges->size(); 393 if (sz != 0) { 394 for (unsigned int i =0; i<sz; i++) { 395 if (ranges->elementAt(i) != null) 396 ranges->elementAt(i)->updateRangeForDeletedNode (oldChild); >> This is when the shit hits the fan (already when i = 0), because elementAt() returns a whacko pointer. The reason for this is that the owner document has now been deleted, indicated by a null-valued ranges member variable. 397 } 398 } 399 } 400 } Brief explanation of how we are using Xerces-C++ in our application: DOMParser objects are pooled, and access to the pool is synchronized. Before a DOMParser object is returned to the pool the DOMParser::reset() is always called to make sure that the DOM_Document object is released by the parser. Thus, the environment is multi-threaded in the sense that different DOMParser objects and different DOM_Document objects are accessed concurrently by different threads, but each object is only accessed by one thread at a time. We use the DOM_Document::importNode() method to copy nodes from one DOM_Document object into another, and the error occurs when the original object is deleted. In the test environment, we parse the exact same XML document several thousand times before the error occurs, so it could hardly be data related. Xerces-C++ was compiled on solaris using g++ (gcc version 2.95.3). Call stack (note: this was generated with Xerces-C++ 1.6.0, but the resulting call stack is essentially identical in 1.5.2): #0 0xfc1561a0 in DOM_Node::operator== (this=0x84, other=@0xfd1014f8) at DOM_Node.cpp:160 #1 0xfc1e45d4 in RangeImpl::updateRangeForDeletedNode (this=0x60, node=0x1c26f8) at RangeImpl.cpp:1623 #2 0xfc1d0a78 in ParentNode::removeChild (this=0x1ef7a0, oldChild=0x1c26f8) at ParentNode.cpp:396 #3 0xfc1c6f9c in NodeImpl::deleteIf (thisNode=0x1ef7a0) at NodeImpl.cpp:209 #4 0xfc1c787c in NodeImpl::unreferenced (this=0x1ef7a0) at NodeImpl.cpp:353 #5 0xfc1ea968 in RefCountedImpl::removeRef (thisNode=0x1ef7a0) at RefCountedImpl.cpp:117 #6 0xfc156124 in DOM_Node::~DOM_Node (this=0x101180, __in_chrg=2) at DOM_Node.cpp:144 #7 0xfc1545b0 in DOM_Element::~DOM_Element (this=0x101180, __in_chrg=2) at DOM_Element.cpp:111 #8 <destructor in our wrapper class> Local variables in ParentNode::removeChild(): *this = {<ChildNode> = {<NodeImpl> = {<NodeListImpl> = {<RefCountedImpl> = {nodeRefCount = 0, _vptr. = 0xfc4c5c50}, <No data fields>}, ownerNode = 0x14c7c8, flags = 0, static READONLY = 1, static SYNCDATA = 2, static SYNCCHILDREN = 4, static OWNED = 8, static FIRSTCHILD = 16, static SPECIFIED = 32, static IGNORABLEWS = 64, static SETVALUE = 128, static ID_ATTR = 256, static USERDATA = 512, static HASSTRING = 1024, static gLiveNodeImpls = 404, static gTotalNodeImpls = 262196}, previousSibling = 0x0, nextSibling = 0x0}, ownerDocument = 0x14c7c8, firstChild = 0x1c26f8, fCachedLength = 3, fCachedChild = 0x1d41c8, fCachedChildIndex = 2} *ownerDocument = {<ParentNode> = {<ChildNode> = {<NodeImpl> = {<NodeListImpl> = {<RefCountedImpl> = {nodeRefCount = 2006649, _vptr. = 0xfc4cb258}, <No data fields>}, ownerNode = 0x0, flags = 0, static READONLY = 1, static SYNCDATA = 2, static SYNCCHILDREN = 4, static OWNED = 8, static FIRSTCHILD = 16, static SPECIFIED = 32, static IGNORABLEWS = 64, static SETVALUE = 128, static ID_ATTR = 256, static USERDATA = 512, static HASSTRING = 1024, static gLiveNodeImpls = 404, static gTotalNodeImpls = 262196}, previousSibling = 0x0, nextSibling = 0x0}, ownerDocument = 0x0, firstChild = 0x0, fCachedLength = -1, fCachedChild = 0x0, fCachedChildIndex = -1}, docType = 0x0, docElement = 0x0, namePool = 0x179b20, fNodeIDMap = 0x0, iterators = 0x0, treeWalkers = 0x0, userData = 0x0, ranges = 0x0, fChanges = 46, errorChecking = 1361856} *ranges = {fAdoptedElems = false, fCurCount = 88, fMaxCount = 0, fElemList = 0x1e9e79} ranges->elementAt(i) = 0x60 --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]