[ 
https://issues.apache.org/jira/browse/XALANJ-2850?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18111018#comment-18111018
 ] 

Andrew Leonard commented on XALANJ-2850:
----------------------------------------

IBM Bob AI analysis of failure:
{color:#000080}**Component:**{color}{color:#000000} 
{color}{color:#800000}`org.apache.xpath.axes.LocPathIterator`{color}
{color:#000080}**Affects:**{color}{color:#000000} Xalan-J 2.7.2, 2.7.3{color}

{color:#800000}### Description{color}

{color:#800000}`LocPathIterator`{color}{color:#000000} maintains an 
{color}{color:#800000}`IteratorPool`{color}{color:#000000} 
({color}{color:#800000}`m_clones`{color}{color:#000000}) of reusable iterator 
instances on the compiled stylesheet expression, shared across all 
{color}{color:#800000}`Transformer`{color}{color:#000000} instances created 
from the same {color}{color:#800000}`Templates`{color}{color:#000000}. Both 
{color}{color:#800000}`execute()`{color}{color:#000000} and 
{color}{color:#800000}`asIterator()`{color}{color:#000000} check out an 
instance from the pool and wrap it in an 
{color}{color:#800000}`XNodeSet`{color}{color:#000000}:{color}

{color:#000000}```java{color}
{color:#267f99}XNodeSet{color}{color:#000000} 
{color}{color:#001080}iter{color}{color:#000000} = 
{color}{color:#af00db}new{color}{color:#000000} 
{color}{color:#795e26}XNodeSet{color}{color:#000000}((LocPathIterator){color}{color:#001080}m_clones{color}{color:#000000}.{color}{color:#795e26}getInstance{color}{color:#000000}());{color}
{color:#001080}iter{color}{color:#000000}.{color}{color:#795e26}setRoot{color}{color:#000000}(contextNode,
 xctxt);{color}
{color:#af00db}return{color}{color:#000000} iter;{color}
{color:#000000}```{color}

{color:#800000}`XNodeSet(DTMIterator)`{color}{color:#000000} stores the passed 
iterator directly as {color}{color:#800000}`m_iter`{color}{color:#000000} — a 
shallow reference, not a clone. When the 
{color}{color:#800000}`XNodeSet`{color}{color:#000000} is consumed and 
{color}{color:#800000}`detach()`{color}{color:#000000} is called, 
{color}{color:#800000}`LocPathIterator.detach()`{color}{color:#000000} returns 
{color}{color:#800000}`this`{color}{color:#000000} to the pool via 
{color}{color:#800000}`m_clones.freeInstance(this)`{color}{color:#000000}. 
However, the {color}{color:#800000}`XNodeSet`{color}{color:#000000} that wraps 
it may still be alive on another thread with 
{color}{color:#800000}`m_iter`{color}{color:#000000} pointing to the now-pooled 
instance.{color}

{color:#000000}If a second thread concurrently calls 
{color}{color:#800000}`getInstance()`{color}{color:#000000} and receives the 
same iterator, it wraps it in a new 
{color}{color:#800000}`XNodeSet`{color}{color:#000000} and calls 
{color}{color:#800000}`setRoot()`{color}{color:#000000} on the same instance 
the first thread's {color}{color:#800000}`XNodeSet`{color}{color:#000000} still 
holds. This is a data race on a shared mutable object.{color}

{color:#000000}Note: 
{color}{color:#800000}`executeCharsToContentHandler()`{color}{color:#000000} 
and {color}{color:#800000}`asNode()`{color}{color:#000000} are not affected — 
they call {color}{color:#800000}`clone.detach()`{color}{color:#000000} 
themselves before returning, so the instance is fully done before it re-enters 
the pool.{color}
 
{color:#800000}### Fix{color}

{color:#000000}Call 
{color}{color:#800000}`allowDetachToRelease(false)`{color}{color:#000000} on 
the checked-out iterator before handing ownership to 
{color}{color:#800000}`XNodeSet`{color}{color:#000000}, so that 
{color}{color:#800000}`detach()`{color}{color:#000000} discards rather than 
pools the instance. This has no functional impact on XPath evaluation results — 
pool reuse continues to work for 
{color}{color:#800000}`asNode()`{color}{color:#000000} and 
{color}{color:#800000}`cloneWithReset()`{color}{color:#000000} which manage 
their own iterator lifecycle.{color}

{color:#000000}```java{color}
{color:#008000}// execute(){color}
{color:#267f99}LocPathIterator{color}{color:#000000} 
{color}{color:#001080}clone{color}{color:#000000} = 
(LocPathIterator){color}{color:#001080}m_clones{color}{color:#000000}.{color}{color:#795e26}getInstance{color}{color:#000000}();{color}
{color:#001080}clone{color}{color:#000000}.{color}{color:#795e26}allowDetachToRelease{color}{color:#000000}({color}{color:#0000ff}false{color}{color:#000000});{color}
{color:#267f99}XNodeSet{color}{color:#000000} 
{color}{color:#001080}iter{color}{color:#000000} = 
{color}{color:#af00db}new{color}{color:#000000} 
{color}{color:#795e26}XNodeSet{color}{color:#000000}(clone);{color}
{color:#001080}iter{color}{color:#000000}.{color}{color:#795e26}setRoot{color}{color:#000000}({color}{color:#001080}xctxt{color}{color:#000000}.{color}{color:#795e26}getCurrentNode{color}{color:#000000}(),
 xctxt);{color}
{color:#af00db}return{color}{color:#000000} iter;{color}

{color:#008000}// asIterator(){color}
{color:#267f99}LocPathIterator{color}{color:#000000} 
{color}{color:#001080}clone{color}{color:#000000} = 
(LocPathIterator){color}{color:#001080}m_clones{color}{color:#000000}.{color}{color:#795e26}getInstance{color}{color:#000000}();{color}
{color:#001080}clone{color}{color:#000000}.{color}{color:#795e26}allowDetachToRelease{color}{color:#000000}({color}{color:#0000ff}false{color}{color:#000000});{color}
{color:#267f99}XNodeSet{color}{color:#000000} 
{color}{color:#001080}iter{color}{color:#000000} = 
{color}{color:#af00db}new{color}{color:#000000} 
{color}{color:#795e26}XNodeSet{color}{color:#000000}(clone);{color}
{color:#001080}iter{color}{color:#000000}.{color}{color:#795e26}setRoot{color}{color:#000000}(contextNode,
 xctxt);{color}
{color:#af00db}return{color}{color:#000000} iter;{color}
{color:#000000}```{color}

> Concurrent XSLT transformation throws "Can not setRoot on a non-iterated 
> NodeSequence" RuntimeException
> -------------------------------------------------------------------------------------------------------
>
>                 Key: XALANJ-2850
>                 URL: https://issues.apache.org/jira/browse/XALANJ-2850
>             Project: XalanJ2
>          Issue Type: Bug
>      Security Level: No security risk; visible to anyone(Ordinary problems in 
> Xalan projects.  Anybody can view the issue.) 
>          Components: Xalan
>    Affects Versions: 2.7.2
>         Environment: Ubuntu armv7 host running with Temurin jdk8 aarch32 JVM.
>            Reporter: Andrew Leonard
>            Priority: Minor
>
> {color:#800000}### Observed Failure{color}
> {color:#000000}Consistent crash under multi-threaded XSLT transformation 
> (DaCapo {color}{color:#800000}`xalan`{color}{color:#000000} benchmark, 4 
> threads, Ubuntu 24.04/aarch32). The race is timing-sensitive and may be 
> masked on fewer-core hardware or on architectures where 
> {color}{color:#800000}`synchronized`{color}{color:#000000} barriers 
> accidentally serialise access.{color}
> {color:#000000}```{color}
> {color:#000000}Caused by: java.lang.RuntimeException: Programmer assertion is 
> incorrect! - Can not setRoot on a non-iterated NodeSequence!{color}
> {color:#000000} at 
> org.apache.xpath.Expression.assertion(Expression.java:423){color}
> {color:#000000} at 
> org.apache.xpath.axes.NodeSequence.setRoot(NodeSequence.java:275){color}
> {color:#000000} at 
> org.apache.xpath.axes.LocPathIterator.asIterator(LocPathIterator.java:269){color}
> {color:#000000} at 
> org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:207){color}
> {color:#000000} at 
> org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178){color}
> {color:#000000} at 
> org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402){color}
> {color:#000000} at 
> org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2272){color}
> {color:#000000} at 
> org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1358){color}
> {color:#000000} at 
> org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:711){color}
> {color:#000000} at 
> org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1275){color}
> {color:#000000} at 
> org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1253){color}
> {color:#000000} at 
> org.dacapo.xalan.XSLTBench$XalanWorker.run(XSLTBench.java:157){color}
> {color:#000000}```{color}
> {color:#000000}This is from an Adoptium AQAvit testcase running Dacapo xalan 
> benchmark.{color}
> {color:#000000}A test grinder job with full console is available here: 
> [https://ci.adoptium.net/job/Grinder/18088/console]{color}
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to