Project

Profile

Help

Bug #6076

closed

NPE in Saxon HE 12.2

Added by Vladimir Nesterovsky 11 months ago. Updated 10 months ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Multithreading
Sprint/Milestone:
-
Start date:
2023-06-15
Due date:
% Done:

100%

Estimated time:
Legacy ID:
Applies to branch:
12, trunk
Fix Committed on Branch:
12, trunk
Fixed in Maintenance Release:
Platforms:
.NET, Java

Description

While trying to upgrade Saxon HE from version 10.6 to 12.2 I get following error. There are not any errors in version 10.6.

     [java] java.lang.RuntimeException: Internal error evaluating function t:allocate-names at line 151 in module classpath:META-INF/stylesheets/csharpxom/csharp-names.xslt
     [java] 	at net.sf.saxon.expr.instruct.UserFunction.call(UserFunction.java:684)
     [java] 	at net.sf.saxon.expr.UserFunctionCall$UserFunctionCallElaborator.lambda$elaborateForPull$0(UserFunctionCall.java:746)
     [java] 	at net.sf.saxon.expr.elab.EagerPullEvaluator.evaluate(EagerPullEvaluator.java:37)
     [java] 	at net.sf.saxon.expr.elab.LearningEvaluator.evaluate(LearningEvaluator.java:59)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$setAllVariables$1(LetExpression.java:861)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:946)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$2(Block.java:867)
     [java] 	at net.sf.saxon.expr.instruct.Choose$ChooseExprElaborator.lambda$elaborateForPush$11(Choose.java:1174)
     [java] 	at net.sf.saxon.expr.instruct.Copy$CopyElaborator.lambda$elaborateForPush$0(Copy.java:589)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.expr.instruct.NextMatch$NextMatchPackage.processLeavingTail(NextMatch.java:170)
     [java] 	at net.sf.saxon.expr.Expression.dispatchTailCall(Expression.java:976)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:651)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$1(Block.java:853)
     [java] 	at net.sf.saxon.expr.instruct.Choose$ChooseExprElaborator.lambda$elaborateForPush$11(Choose.java:1173)
     [java] 	at net.sf.saxon.expr.instruct.Copy$CopyElaborator.lambda$elaborateForPush$0(Copy.java:589)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.expr.instruct.NextMatch$NextMatchPackage.processLeavingTail(NextMatch.java:170)
     [java] 	at net.sf.saxon.expr.Expression.dispatchTailCall(Expression.java:976)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:651)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$1(Block.java:853)
     [java] 	at net.sf.saxon.expr.instruct.Choose$ChooseExprElaborator.lambda$elaborateForPush$11(Choose.java:1173)
     [java] 	at net.sf.saxon.expr.instruct.Copy$CopyElaborator.lambda$elaborateForPush$0(Copy.java:589)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.expr.instruct.NextMatch$NextMatchPackage.processLeavingTail(NextMatch.java:170)
     [java] 	at net.sf.saxon.expr.Expression.dispatchTailCall(Expression.java:976)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:651)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$1(Block.java:853)
     [java] 	at net.sf.saxon.expr.instruct.Choose$ChooseExprElaborator.lambda$elaborateForPush$11(Choose.java:1173)
     [java] 	at net.sf.saxon.expr.instruct.Copy$CopyElaborator.lambda$elaborateForPush$0(Copy.java:589)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.expr.instruct.NextMatch$NextMatchPackage.processLeavingTail(NextMatch.java:170)
     [java] 	at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:457)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:650)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$1(Block.java:853)
     [java] 	at net.sf.saxon.expr.instruct.Choose$ChooseExprElaborator.lambda$elaborateForPush$11(Choose.java:1173)
     [java] 	at net.sf.saxon.expr.instruct.Copy$CopyElaborator.lambda$elaborateForPush$0(Copy.java:589)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.expr.instruct.NextMatch$NextMatchPackage.processLeavingTail(NextMatch.java:170)
     [java] 	at net.sf.saxon.expr.Expression.dispatchTailCall(Expression.java:976)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:651)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$1(Block.java:853)
     [java] 	at net.sf.saxon.expr.instruct.Choose$ChooseExprElaborator.lambda$elaborateForPush$11(Choose.java:1173)
     [java] 	at net.sf.saxon.expr.instruct.Copy$CopyElaborator.lambda$elaborateForPush$0(Copy.java:589)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.expr.instruct.NextMatch$NextMatchPackage.processLeavingTail(NextMatch.java:170)
     [java] 	at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:457)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:650)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$1(Block.java:853)
     [java] 	at net.sf.saxon.expr.instruct.Choose$ChooseExprElaborator.lambda$elaborateForPush$11(Choose.java:1173)
     [java] 	at net.sf.saxon.expr.instruct.Copy$CopyElaborator.lambda$elaborateForPush$0(Copy.java:589)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.expr.instruct.NextMatch$NextMatchPackage.processLeavingTail(NextMatch.java:170)
     [java] 	at net.sf.saxon.expr.Expression.dispatchTailCall(Expression.java:976)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:651)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$1(Block.java:853)
     [java] 	at net.sf.saxon.expr.instruct.Choose$ChooseExprElaborator.lambda$elaborateForPush$11(Choose.java:1173)
     [java] 	at net.sf.saxon.expr.instruct.Copy$CopyElaborator.lambda$elaborateForPush$0(Copy.java:589)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.expr.instruct.NextMatch$NextMatchPackage.processLeavingTail(NextMatch.java:170)
     [java] 	at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:457)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:650)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$1(Block.java:853)
     [java] 	at net.sf.saxon.expr.instruct.Choose$ChooseExprElaborator.lambda$elaborateForPush$11(Choose.java:1173)
     [java] 	at net.sf.saxon.expr.instruct.Copy$CopyElaborator.lambda$elaborateForPush$0(Copy.java:589)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.expr.instruct.NextMatch$NextMatchPackage.processLeavingTail(NextMatch.java:170)
     [java] 	at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:457)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:650)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$2(Block.java:867)
     [java] 	at net.sf.saxon.expr.instruct.Choose$ChooseExprElaborator.lambda$elaborateForPush$11(Choose.java:1174)
     [java] 	at net.sf.saxon.expr.instruct.Copy$CopyElaborator.lambda$elaborateForPush$0(Copy.java:589)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.expr.instruct.NextMatch$NextMatchPackage.processLeavingTail(NextMatch.java:170)
     [java] 	at net.sf.saxon.expr.Expression.dispatchTailCall(Expression.java:976)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:651)
     [java] 	at net.sf.saxon.expr.elab.PushElaborator.lambda$elaborateForPull$0(PushElaborator.java:38)
     [java] 	at net.sf.saxon.expr.CardinalityChecker$CardinalityCheckerElaborator.lambda$elaborateForPull$0(CardinalityChecker.java:502)
     [java] 	at net.sf.saxon.expr.ItemChecker$ItemCheckerElaborator.lambda$elaborateForPull$0(ItemChecker.java:453)
     [java] 	at net.sf.saxon.expr.elab.EagerPullEvaluator.evaluate(EagerPullEvaluator.java:37)
     [java] 	at net.sf.saxon.expr.elab.LearningEvaluator.evaluate(LearningEvaluator.java:59)
     [java] 	at net.sf.saxon.expr.TailCallLoop.tailCallDifferentFunction(TailCallLoop.java:156)
     [java] 	at net.sf.saxon.expr.TailCallLoop.access$200(TailCallLoop.java:28)
     [java] 	at net.sf.saxon.expr.TailCallLoop$TailCallLoopElaborator.lambda$elaborateForPush$1(TailCallLoop.java:247)
     [java] 	at net.sf.saxon.expr.instruct.UserFunction.process(UserFunction.java:707)
     [java] 	at net.sf.saxon.expr.UserFunctionCall$UserFunctionCallElaborator.lambda$elaborateForPush$4(UserFunctionCall.java:833)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$2(Block.java:867)
     [java] 	at net.sf.saxon.expr.instruct.FixedElement$FixedElementElaborator.lambda$elaborateForPush$0(FixedElement.java:640)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.instruct.FixedElement$FixedElementElaborator.lambda$elaborateForPush$0(FixedElement.java:640)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$4(Block.java:895)
     [java] 	at net.sf.saxon.expr.CardinalityChecker$CardinalityCheckerElaborator.lambda$elaborateForPush$1(CardinalityChecker.java:521)
     [java] 	at net.sf.saxon.expr.instruct.NamedTemplate.expand(NamedTemplate.java:269)
     [java] 	at net.sf.saxon.expr.instruct.CallTemplate$CallTemplateElaborator.lambda$elaborateForPush$1(CallTemplate.java:633)
     [java] 	at net.sf.saxon.expr.elab.PushElaborator.lambda$elaborateForItem$2(PushElaborator.java:77)
     [java] 	at net.sf.saxon.expr.elab.OptionalItemEvaluator.evaluate(OptionalItemEvaluator.java:41)
     [java] 	at net.sf.saxon.expr.instruct.Choose$EagerChooseEvaluator.evaluate(Choose.java:1248)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$setAllVariables$4(LetExpression.java:905)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:946)
     [java] 	at net.sf.saxon.expr.TryCatch$TryCatchElaborator.lambda$elaborateForPush$1(TryCatch.java:340)
     [java] 	at net.sf.saxon.expr.LetExpression$LetExprElaborator.lambda$elaborateForPush$6(LetExpression.java:948)
     [java] 	at net.sf.saxon.expr.instruct.Block$BlockElaborator.lambda$elaborateForPush$2(Block.java:867)
     [java] 	at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:393)
     [java] 	at net.sf.saxon.trans.Mode.handleRuleNotNull(Mode.java:568)
     [java] 	at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:502)
     [java] 	at net.sf.saxon.expr.instruct.ApplyTemplates$ApplyTemplatesElaborator.lambda$elaborateForPush$1(ApplyTemplates.java:650)
     [java] 	at net.sf.saxon.expr.elab.EagerPushEvaluator.evaluate(EagerPushEvaluator.java:45)
     [java] 	at net.sf.saxon.expr.parser.ExpressionTool.eagerEvaluate(ExpressionTool.java:195)
...
     [java] Caused by: java.lang.NullPointerException: Cannot invoke "net.sf.saxon.expr.elab.SequenceEvaluator.evaluate(net.sf.saxon.expr.XPathContext)" because "eagerEvaluator" is null
     [java] 	at net.sf.saxon.expr.instruct.LocalParamBlock$LocalParamBlockElaborator.lambda$elaborateForPush$0(LocalParamBlock.java:147)
     [java] 	at net.sf.saxon.expr.instruct.IterateInstr$IterateElaborator.lambda$elaborateForPush$0(IterateInstr.java:364)
     [java] 	at net.sf.saxon.expr.elab.PushElaborator.lambda$elaborateForPull$0(PushElaborator.java:38)
     [java] 	at net.sf.saxon.expr.Atomizer$AtomizerElaborator.lambda$elaborateForPull$0(Atomizer.java:676)
     [java] 	at net.sf.saxon.expr.UntypedSequenceConverter$UntypedSequenceConverterElaborator.lambda$elaborateForPull$0(UntypedSequenceConverter.java:304)
     [java] 	at net.sf.saxon.expr.ItemChecker$ItemCheckerElaborator.lambda$elaborateForPull$0(ItemChecker.java:453)
     [java] 	at net.sf.saxon.expr.elab.EagerPullEvaluator.evaluate(EagerPullEvaluator.java:37)
     [java] 	at net.sf.saxon.expr.LetExpression$EagerLocalVariableEvaluator.evaluate(LetExpression.java:1008)
     [java] 	at net.sf.saxon.expr.LetExpression$EagerLocalVariableEvaluator.evaluate(LetExpression.java:1008)
     [java] 	at net.sf.saxon.expr.instruct.Choose$EagerChooseEvaluator.evaluate(Choose.java:1248)
     [java] 	at net.sf.saxon.expr.elab.LearningEvaluator.evaluate(LearningEvaluator.java:59)
     [java] 	at net.sf.saxon.expr.instruct.UserFunction.call(UserFunction.java:674)
     [java] 	... 141 more

My attempts to figure out how this NPE could ever occur lead nowhere.


Files

csharp-names.xslt (7.64 KB) csharp-names.xslt xslt stylesheet Vladimir Nesterovsky, 2023-06-15 13:32
Actions #1

Updated by Michael Kay 11 months ago

Thanks. Any chance of putting together a repro? It's very rarely possible to diagnose a problem from the stack trace alone; and even if we can make a conjecture, it's impossible to test the fix without a repro.

It might help to know that at the point of failure we are trying to evaluate the initial values of the xsl:param elements within an xsl:iterate instruction. On the first-time-through code we attempt to construct an evaluator for each of these parameters, and the NPE occurs because after doing this, one of the parameters has a null evaluator. The first thing we would need to know is what the initialization expression actually looks like.

Actions #2

Updated by Vladimir Nesterovsky 11 months ago

Sure, I'll try to create a small repo if, I can. This won't be easy.

On the other hand, per stack trace, error happens at net.sf.saxon.expr.instruct.LocalParamBlock$LocalParamBlockElaborator:

        public PushEvaluator elaborateForPush() {
            LocalParamBlock expr = (LocalParamBlock) getExpression();
            paramEval = new SequenceEvaluator[expr.operanda.length];
            for (int i=0; i<expr.operanda.length; i++) {
                paramEval[i] = expr.operanda[i].getChildExpression().makeElaborator().eagerly();
            }
            return (out, context) -> {
                for (SequenceEvaluator eagerEvaluator : paramEval) {
                    eagerEvaluator.evaluate(context); <-- RIGHT HERE (because "eagerEvaluator" is null)
                }
                return null;
            };
        }

I tried to find under what circumstances eagerEvaluator, which can only happen, in my opinion, when ...eagerly() returns null. I checked all implementations of this method and found that they either throw or return some non null instance.

Actions #3

Updated by Vladimir Nesterovsky 11 months ago

Right now only thing I can supply from code looking at log is stylesheet csharp-names.xslt with function t:allocate-names. From java stack it's hard to me to figure out how it's called.

Actions #4

Updated by Michael Kay 11 months ago

Thanks. I've put the key elements into a working stylesheet, which doesn't crash, but at least I can debug into it to see what's going on.

Actions #5

Updated by Vladimir Nesterovsky 11 months ago

Let me complicate it a little.

Another run crashed with NPE but in completely different xslt module. This looks like parts of code step on each other's toes.

Actions #6

Updated by Vladimir Nesterovsky 11 months ago

What does happen if stylesheet is used from multiple threads? I have a batch that separates work between threads and reuses compiled stylesheets.

I don't remember all details now but when it was implemented, it followed all good practices of safely reuse of compiled stylesheets.

Actions #7

Updated by Michael Kay 11 months ago

OK thanks for the hint. Will investigate.

Actions #8

Updated by Michael Kay 11 months ago

Yes, you might well be right.

Every Expression is supposed to have one Elaborator, created on first execution. All threads executing the same code share the same Elaborator.

Expression.makeElaborator() should probably therefore be synchronized, though I don't think that's essential.

What's problematic is that LocalParamBlockElaborator.elaborateForPush() updates the Elaborator's instance data in an unsafe way. If it's called simultaneously in different threads, it can set paramEval to null while another thread is relying on it. And of course, the same problem might occur in other classes as well.

Actions #9

Updated by Michael Kay 11 months ago

There's another thing wrong here, which is that when we evaluate a function call in push mode, we are creating a new Elaborator (and thus essentially rebuilding the execution engine) on each call. Specifically, the execution method of the PushEvaluator returned by UserFunctionCall.elaborateForPush() calls targetFunction.process(), which calls getBody().makeElaborator().elaborateForPush().processLeavingTail(output, context). This is a performance issue rather than a multi-threading issue, but it makes the multithreading issue much more likely to be triggered.

Contrast with UserFunction.call(), used for pull-mode evaluation, which only creates a new bodyEvaluator on the first time through (this too should be synchronized).

Actions #10

Updated by Michael Kay 11 months ago

I'm going to try and find out if any other Elaborator subclasses make the same mistake as LocalParamBlockElaborator of updating a local field.

Fortunately the Java-to-C# transpilation leaves me with an XML version of the entire Java code which I can query. It should be enough to search for a member element with name/identifier => ends-with('Elaborator') that has a members/member[@nodeType='FieldDeclaration'].

For reference the query is

collection('build/ee_xmlout?recurse=yes;select=*.xml')//member[name/@identifier=>ends-with('Elaborator') and
 members/member/@nodeType='FieldDeclaration']/name/string(@identifier)

and the result is:

FunctionCallElaborator 
ChooseExprElaborator 
LocalParamBlockElaborator 
ConditionalBlockElaborator 
LetExprElaborator 
MultithreadedForEachElaborator

Some of these are false alarms (the only member fields are final static, or the updates are synchronised) but two or three of them need a more careful look.

Actions #11

Updated by Michael Kay 11 months ago

Running the stylesheet multithreaded, I have reproduced the failure.

Actions #12

Updated by Michael Kay 11 months ago

In LocalParamBlockElaborator the solution is simple: just make paramEval into a local variable within the elaborateForPush() method. The test case no longer crashes.

Actions #13

Updated by Michael Kay 11 months ago

Other classes examined:

FunctionCallElaborator - this updates the local argumentEvaluators field during the setExpression() call. To make this safe we must synchronise Expression.makeElaborator().

ChooseExprElaborators - updates the local conditions evaluators. The method makeConditionEvaluators is synchronized so it's probably OK.

ConditionalBlockElaborator - uses final static fields only.

LetExprElaborator - has a local field finalAction. This is set from setAllVariables() which is called from the various elaborate methods, e.g. elaborateForPull(). Although in an ideal world these methods are only called once, we can't rely on that, so this feels unsafe. However, I don't think this field is needed. The value can be returned from setAllVariables() to its caller in an output parameter.

MultithreadedForEachElaborator - the field is not needed and can be replaced by a local variable.

Actions #14

Updated by Vladimir Nesterovsky 11 months ago

I think I know the answer to my next question, yet I'll ask: what are chances to have fixes ready on maven soon?

Actions #15

Updated by Michael Kay 11 months ago

  • Category set to Multithreading
  • Status changed from New to Resolved
  • Assignee set to Michael Kay
  • Priority changed from Low to Normal
  • Applies to branch trunk added
  • Fix Committed on Branch 12, trunk added
  • Platforms .NET, Java added
Actions #16

Updated by Michael Kay 11 months ago

Answer to your question: this kind of bug makes us think that it might be time to start preparing the next maintenance release. But no immediate promises.

Actions #17

Updated by O'Neil Delpratt 10 months ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in Maintenance Release 12.3 added

Bug fix applied in the Saxon 12.3 maintenance release.

Please register to edit this issue

Also available in: Atom PDF