Dean,
My apologies for not replying sooner. I was just getting caught up, and finally found a message the pointed to a working mail archive...
I don't think your comment makes sense. In this case, a janitor doesn't make sense since the lifetime of the buffer is not the automatic scope that a janitor could provide - the buffer needs to stick around past the call to SAX2XMLReaderImpl::startElement.
I think the correct resolution is to ensure that the prefix stack mechanism gets reset each time the XMLReader is used. For example, add the following function to SAX2XMLReaderImpl:
void SAX2XMLReaderImpl::resetPrefixStack()
{
// Pop any prefix buffers left over from previous uses of this XMLReader
while (!prefixCounts->empty())
{
unsigned int numPrefix = prefixCounts->pop();
for (unsigned int i = 0; i < numPrefix; i++)
{
XMLBuffer * buf = fPrefixes->pop() ;
fStringBuffers.releaseBuffer(*buf) ;
}
}
}
In each override of SAX2XMLReaderImpl::parse, call the function to ensure that the buffers are reset, as in:
void SAX2XMLReaderImpl::parse (const InputSource& source)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
try
{
resetPrefixStack();
fParseInProgress = true;
fScanner->scanDocument(source, freuseValidator);
fParseInProgress = false;
}
catch (...)
{
fParseInProgress = false;
throw;
}
}
This fixes the problem for me. I'm CVS-impaired, so if someone would like to make the fix, I'd appreciate it.
Andy Neilson
Technical Architect
webplan Inc.
_________________________________
No code should bid on buffers directly, in general, but instead use the
supplied buffer bid janitor classes that will insure that the buffers get
released upon exit.
--------------
Dean Roddey
Software Geek Extraordinaire
Portal, Inc
[EMAIL PROTECTED]
-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]]
Sent: Thursday, April 12, 2001 2:13 PM
To: [EMAIL PROTECTED]
Subject: [Bug 1329] New - SAX2XMLReaderImpl leaks XMLBuffers
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=1329
*** shadow/1329 Thu Apr 12 14:12:44 2001
--- shadow/1329.tmp.26322 Thu Apr 12 14:12:44 2001
***************
*** 0 ****
--- 1,127 ----
+
+===========================================================================
=+
+ | SAX2XMLReaderImpl leaks XMLBuffers
|
+
+---------------------------------------------------------------------------
-+
+ | Bug #: 1329 Product: Xerces-C
|
+ | Status: NEW Version: 1.4
|
+ | Resolution: Platform: PC
|
+ | Severity: Major OS/Version:
|
+ | Priority: Component: SAX/SAX2
|
+
+---------------------------------------------------------------------------
-+
+ | Assigned To: [EMAIL PROTECTED]
|
+ | Reported By: [EMAIL PROTECTED]
|
+ | CC list: Cc:
|
+
+---------------------------------------------------------------------------
-+
+ | URL:
|
+
+===========================================================================
=+
+ | DESCRIPTION
|
+ Overview Description:
+ The implementations of SAX2XMLReaderImpl::startElement and
+ SAX2XMLReaderImpl::endElement will leak buffers in the case where the
+ ContentHandler throws an exception. If you reuse instances of the same
+ XMLReader repeatedly, XMLBufferManager::bidOnBuffer will eventually throw
an
+ XMLExcepts::BufMgr_NoMoreBuffers.
+
+ Steps to Reproduce:
+ The following sample code illustrates this problem (built using Microsoft
+ Visual C++ 6 SP5):
+
//--------------------------------------------------------------------------
---
+ // SAX2BufferLeak.cpp - demonstrates a bug in Xerces-c 1.4.0
+ #include "stdafx.h"
+
+ #include <iostream>
+
+ #include <util/PlatformUtils.hpp>
+ #include <sax2/DefaultHandler.hpp>
+ #include <sax2/XMLReaderFactory.hpp>
+ #include <framework/MemBufInputSource.hpp>
+
+ using namespace std;
+
+
+ class ErrorThrowingContentHandler : public DefaultHandler
+ {
+ public:
+
+ virtual void startElement(
+ const XMLCh* const uri,
+ const XMLCh* const localname,
+ const XMLCh* const qname,
+ const Attributes& attributes)
+ {
+ throw true;
+ };
+
+ virtual void fatalError(const SAXParseException& exception)
+ {
+ throw exception;
+ };
+
+ };
+
+
+ int main(int argc, char* argv[])
+ {
+ XMLPlatformUtils::Initialize();
+
+ SAX2XMLReader* reader = XMLReaderFactory::createXMLReader();
+
+ ErrorThrowingContentHandler* handler = new
ErrorThrowingContentHandler
+ ();
+ reader->setContentHandler(handler);
+ reader->setErrorHandler(handler);
+
+ for (size_t i = 0; i < 35; i++)
+ {
+ MemBufInputSource is((XMLByte*)"<x:e1
+ xmlns:x=\"urn:mynamespace\"></x:e1>", 39, L"FakeSystemID");
+
+ try
+ {
+ reader->parse(is);
+ }
+ catch(bool)
+ {
+ // Do nothing - we expect this to happen
+ }
+ catch(SAXParseException& e)
+ {
+ wcout << L"SAXParseException" << endl
+ << L"i=" << i << endl
+ << L"Message: " << e.getMessage() <<
+ endl;
+ break;
+ }
+ }
+
+ XMLPlatformUtils::Terminate();
+
+ return 0;
+ }
+
//--------------------------------------------------------------------------
---
+
+ This program will print the following on the console:
+
+ SAXParseException
+ i=31
+ Message: An exception occured! Type:RuntimeException, Message:The buffer
manager
+ cannot provide any more buffers
+
+ Expected Results:
+ The above program should print out nothing.
+
+ Additional Information:
+ SAX2XMLReaderImpl does not manage the fStringBuffer, fPrefixes and
prefixCounts
+ members properly in the case where:
+
+ - The document uses namespaces.
+ - An errorHandler stops the parse by throwing an exception.
+
+ This problem only becomes apparent when you attempt to reuse a
SAX2XMLReader
+ repeatedly. The case in point is in the SOAP service we have implemented.
It
+ maintains a thread pool with a complete SAX pipeline setup on each thread.
This
+ is critical for performance reasons (and is a generally good approch when
+ possible).
+
+ Possible solutions include try/catch blocks to SAX2XMLReader::startElement
and
+ SAX2XMLReader::endElement, or simply ensuring the the fStringBuffer,
fPrefixes
+ and prefixCount (any others?) are reset properly on each reuse of the
parser.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
