You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-dev@xerces.apache.org by bu...@apache.org on 2001/12/11 17:35:28 UTC

DO NOT REPLY [Bug 5359] New: - Document reference counting fails in multi-threaded multi-processor environment

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: xerces-c-dev@xml.apache.org
        ReportedBy: mikael.carlstedt@st.se


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: xerces-c-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-c-dev-help@xml.apache.org