[
https://issues.apache.org/jira/browse/COCOON-1985?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12465800
]
Ellis Pritchard commented on COCOON-1985:
-----------------------------------------
Ok, attached are a very simple sitemap and XSL stylesheet which demonstrates
the lock up with the unpatched code.
Stack-trace:
Thread [http-41501-Processor25] (Suspended)
owns: ToXMLSAXHandler (id=84)
waiting for: Object (id=83)
Object.wait(long) line: not available [native method]
Object.wait() line: 429
CachingProcessingPipeline(AbstractCachingProcessingPipeline).waitForLock(Object)
line: 187
CachingProcessingPipeline(AbstractCachingProcessingPipeline).validatePipeline(Environment)
line: 684
CachingProcessingPipeline(AbstractCachingProcessingPipeline).setupPipeline(Environment)
line: 724
CachingProcessingPipeline(AbstractProcessingPipeline).preparePipeline(Environment)
line: 501
CachingProcessingPipeline(AbstractProcessingPipeline).prepareInternal(Environment)
line: 515
SitemapSource.init() line: 342
SitemapSource.<init>(ComponentManager, String, Map, Logger) line: 214
SitemapSourceFactory.getSource(String, Map) line: 65
SourceResolverImpl.resolveURI(String, String, Map) line: 208
CocoonComponentManager.resolveURI(String, String, Map) line: 558
HttpEnvironment(AbstractEnvironment).resolveURI(String, String, Map)
line: 553
HttpEnvironment(AbstractEnvironment).resolveURI(String) line: 540
IncludeTransformer$IncludeElement.process0(ContentHandler,
LexicalHandler) line: 560
IncludeTransformer$IncludeElement.process(ContentHandler,
LexicalHandler) line: 538
IncludeTransformer$IncludeXMLPipe.endElement(String, String, String)
line: 916
IncludeTransformer(AbstractXMLPipe).endElement(String, String, String)
line: 112
ToXMLSAXHandler.endElement(String, String, String) line: 261
ElemLiteralResult.execute(TransformerImpl) line: 1399
TransformerImpl.executeChildTemplates(ElemTemplateElement, boolean)
line: 2411
ElemLiteralResult.execute(TransformerImpl) line: 1374
TransformerImpl.executeChildTemplates(ElemTemplateElement, boolean)
line: 2411
TransformerImpl.applyTemplateToNode(ElemTemplateElement, ElemTemplate,
int) line: 2281
TransformerImpl.transformNode(int) line: 1367
TransformerImpl.run() line: 3458
TransformerHandlerImpl.endDocument() line: 406
TraxTransformer(AbstractXMLPipe).endDocument() line: 56
TraxTransformer.endDocument() line: 586
EnvironmentChanger.endDocument() line: 119
XMLTeePipe.endDocument() line: 71
SAXParserImpl$JAXPSAXParser(AbstractSAXParser).endDocument(Augmentations) line:
not available
XMLNSDocumentScannerImpl(XMLDocumentScannerImpl).endEntity(String,
Augmentations) line: not available
XMLEntityManager.endEntity() line: not available
XMLEntityScanner.load(int, boolean) line: not available
XMLEntityScanner.skipSpaces() line: not available
XMLDocumentScannerImpl$TrailingMiscDispatcher.dispatch(boolean) line:
not available
XMLNSDocumentScannerImpl(XMLDocumentFragmentScannerImpl).scanDocument(boolean)
line: not available
XML11Configuration.parse(boolean) line: not available
XML11Configuration.parse(XMLInputSource) line: not available
SAXParserImpl$JAXPSAXParser(XMLParser).parse(XMLInputSource) line: not
available
SAXParserImpl$JAXPSAXParser(AbstractSAXParser).parse(InputSource) line:
not available
SAXParserImpl$JAXPSAXParser.parse(InputSource) line: not available
JaxpParser.parse(InputSource, ContentHandler, LexicalHandler) line: 315
JaxpParser.parse(InputSource, ContentHandler) line: 334
SourceUtil.parse(ServiceManager, Source, ContentHandler) line: 326
FileGenerator.generate() line: 116
CachingProcessingPipeline(AbstractCachingProcessingPipeline).processXMLPipeline(Environment)
line: 333
CachingProcessingPipeline(AbstractProcessingPipeline).process(Environment,
XMLConsumer) line: 780
SitemapSource.toSAX(ContentHandler) line: 413
SourceUtil.toSAX(XMLizable, ContentHandler) line: 101
SourceUtil.parse(ServiceManager, Source, ContentHandler) line: 321
FileGenerator.generate() line: 116
CachingProcessingPipeline(AbstractCachingProcessingPipeline).processXMLPipeline(Environment)
line: 367
CachingProcessingPipeline(AbstractProcessingPipeline).process(Environment)
line: 481
SerializeNode.invoke(Environment, InvokeContext) line: 121
MatchNode(AbstractParentProcessingNode).invokeNodes(ProcessingNode[],
Environment, InvokeContext, String, Map) line: 47
MatchNode.invoke(Environment, InvokeContext) line: 108
PipelineNode(AbstractParentProcessingNode).invokeNodes(ProcessingNode[],
Environment, InvokeContext) line: 69
PipelineNode.invoke(Environment, InvokeContext) line: 143
PipelinesNode(AbstractParentProcessingNode).invokeNodes(ProcessingNode[],
Environment, InvokeContext) line: 69
PipelinesNode.invoke(Environment, InvokeContext) line: 93
ConcreteTreeProcessor.process(Environment, InvokeContext) line: 235
ConcreteTreeProcessor.process(Environment) line: 177
TreeProcessor.process(Environment) line: 253
MountNode.invoke(Environment, InvokeContext) line: 118
MatchNode(AbstractParentProcessingNode).invokeNodes(ProcessingNode[],
Environment, InvokeContext, String, Map) line: 47
MatchNode.invoke(Environment, InvokeContext) line: 108
PipelineNode(AbstractParentProcessingNode).invokeNodes(ProcessingNode[],
Environment, InvokeContext) line: 69
PipelineNode.invoke(Environment, InvokeContext) line: 143
PipelinesNode(AbstractParentProcessingNode).invokeNodes(ProcessingNode[],
Environment, InvokeContext) line: 69
PipelinesNode.invoke(Environment, InvokeContext) line: 93
ConcreteTreeProcessor.process(Environment, InvokeContext) line: 235
ConcreteTreeProcessor.process(Environment) line: 177
TreeProcessor.process(Environment) line: 253
Cocoon.process(Environment) line: 699
WispersCocoonServlet(CocoonServlet).service(HttpServletRequest,
HttpServletResponse) line: 1155
WispersCocoonServlet(HttpServlet).service(ServletRequest,
ServletResponse) line: 853
ApplicationFilterChain.internalDoFilter(ServletRequest,
ServletResponse) line: 237
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line:
157
StandardWrapperValve.invoke(Request, Response, ValveContext) line: 214
StandardValveContext.invokeNext(Request, Response) line: 104
StandardPipeline.invoke(Request, Response) line: 520
StandardContextValve.invokeInternal(Wrapper, Request, Response) line:
198
StandardContextValve.invoke(Request, Response, ValveContext) line: 144
StandardValveContext.invokeNext(Request, Response) line: 104
AccessLogValve.invoke(Request, Response, ValveContext) line: 535
StandardValveContext.invokeNext(Request, Response) line: 102
StandardPipeline.invoke(Request, Response) line: 520
StandardHostValve.invoke(Request, Response, ValveContext) line: 137
StandardValveContext.invokeNext(Request, Response) line: 104
ErrorReportValve.invoke(Request, Response, ValveContext) line: 117
StandardValveContext.invokeNext(Request, Response) line: 102
StandardPipeline.invoke(Request, Response) line: 520
StandardEngineValve.invoke(Request, Response, ValveContext) line: 109
StandardValveContext.invokeNext(Request, Response) line: 104
StandardPipeline.invoke(Request, Response) line: 520
StandardEngine(ContainerBase).invoke(Request, Response) line: 929
CoyoteAdapter.service(Request, Response) line: 160
Http11Processor.process(InputStream, OutputStream) line: 799
Http11Protocol$Http11ConnectionHandler.processConnection(TcpConnection,
Object[]) line: 705
TcpWorkerThread.runIt(Object[]) line: 577
ThreadPool$ControlRunnable.run() line: 683
ThreadWithAttributes(Thread).run() line: 534
> AbstractCachingProcessingPipeline locking with IncludeTransformer may hang
> pipeline
> -----------------------------------------------------------------------------------
>
> Key: COCOON-1985
> URL: https://issues.apache.org/jira/browse/COCOON-1985
> Project: Cocoon
> Issue Type: Bug
> Components: * Cocoon Core
> Affects Versions: 2.1.9, 2.1.10, 2.1.11-dev (Current SVN)
> Reporter: Ellis Pritchard
> Priority: Critical
> Attachments: includer.xsl, patch.txt, sitemap.xmap
>
>
> Cocoon 2.1.9 introduced the concept of a lock in
> AbstractCachingProcessingPipeline, an optimization to prevent two concurrent
> requests from generating the same cached content. The first request adds the
> pipeline key to the transient cache to 'lock' the cache entry for that
> pipeline, subsequent concurrent requests wait for the first request to cache
> the content (by Object.lock()ing the pipeline key entry) before proceeding,
> and can then use the newly cached content.
> However, this has introduced an incompatibility with the IncludeTransformer:
> if the inclusions access the same yet-to-be-cached content as the root
> pipeline, the whole assembly hangs, since a lock will be made on a lock
> already held by the same thread, and which cannot be satisfied.
> e.g.
> i) Root pipeline generates using sub-pipeline cocoon:/foo.xml
> ii) the cocoon:/foo.xml sub-pipeline adds it's pipeline key to the transient
> store as a lock.
> iii) subsequently in the root pipeline, the IncludeTransformer is run.
> iv) one of the inclusions also generates with cocoon:/foo.xml, this
> sub-pipeline locks in AbstractProcessingPipeline.waitForLock() because the
> sub-pipeline key is already present.
> v) deadlock.
> I've found a (partial, see below) solution for this: instead of a plain
> Object being added to the transient store as the lock object, the
> Thread.currentThread() is added; when waitForLock() is called, if the lock
> object exists, it checks that it is not the same thread before attempting to
> lock it; if it is the same thread, then waitForLock() returns success, which
> allows generation to proceed. You loose the efficiency of generating the
> cache only once in this case, but at least it doesn't hang! With JDK1.5 this
> can be made neater by using Thread#holdsLock() instead of adding the thread
> object itself to the transient store.
> See patch file.
> However, even with this fix, parallel includes (when enabled) may still hang,
> because they pass the not-the-same-thread test, but fail because the root
> pipeline, which holds the initial lock, cannot complete (and therefore
> statisfy the lock condition for the parallel threads), before the threads
> themselves have completed, which then results in a deadlock again.
> The complete solution is probably to avoid locking if the lock is held by the
> same top-level Request, but that requires more knowledge of Cocoon's
> processing than I (currently) have!
> IMHO unless a complete solution is found to this, then this optimization
> should be removed completely, or else made optional by configuration, since
> it renders the IncludeTransformer dangerous.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
https://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira