[
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]