[ 
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

        

Reply via email to