Rikkola opened a new issue, #2338:
URL: https://github.com/apache/incubator-kie-issues/issues/2338
Evaluating a rule with two subnetwork not nodes — not(and(...)), each with
its own correlation memory — in an event-processing (STREAM) session throws a
NullPointerException on the right-tuple delete path. Pure mainline: plain
PatternDSL, no sequencing or temporal constructs.
Stack trace
```
java.lang.NullPointerException: Cannot invoke "...TupleList.remove(...)"
because the return value of "...TupleImpl.getMemory()" is null
at
PhreakSubnetworkNotExistsNode.deleteRight(PhreakSubnetworkNotExistsNode.
java:92)
at PhreakSubnetworkNotExistsNode.doSubNetworkNode(...)
at PhreakNotNode.doNode(...)
```
Root cause
In the right-delete loop, the code dereferences the right tuple's
memoryunconditionally:
```
// don't use matches here, as it may be null, if the LT was also being
removed.
rightTuple.getMemory().remove(rightTuple);
```
Under this topology a subnetwork right tuple whose insert was staged then
unstaged in the same evaluation cycle reaches the delete having never entered
the matches list, so getMemory() is null and .remove(...) NPEs.
The sibling PhreakNotNode.doRightDeletes already guards this exact case ("it
may have been staged and never actually added"); the subnetwork variant
(PhreakSubnetworkNotExistsNode / RuleNetworkEvaluatorImpl.doSubnetwork2) does
not — its delete loop cancels the pending right INSERT (removeInsert) but then
falls through and addDeletes it anyway, producing a phantom delete against null
memory. This diverges from TupleSetsImpl.addDelete, which returns after an
INSERT/DELETE clash.
Conditions (all load-bearing)
Dropping any of these stops the reproduction:
- STREAM (EventProcessingOption.STREAM) — CLOUD mode does not reproduce.
- Two subnetwork not(and(...)) nodes, each with its own correlation memory.
- Event-role facts.
Reproducer
PatternDSL rule, two event types, STREAM mode:
```
Rule rule = rule("twoSubnetworkNots").build(
not(and(pattern(eventA1).expr(x -> true), pattern(eventB1).expr(x
->
true))),
not(and(pattern(eventA2).expr(x -> true), pattern(eventB2).expr(x
->
true))),
execute(() -> { }));
KieBase kieBase = KieBaseBuilder.createKieBaseFromModel(
new ModelImpl().addRule(rule), EventProcessingOption.STREAM);
KieSession ksession = kieBase.newKieSession();
ksession.insert(new EventA(0)); ksession.fireAllRules();
ksession.insert(new EventB(1)); ksession.fireAllRules(); // NPE here
```
(Distilled from a randomized sequencing stress harness — MODEL_AFTER
reference path, shape 46/seed 42.)
Environment
- Affects drools-core Phreak runtime.
Suggested fix
Guard the null memory in the subnetwork delete path, mirroring
PhreakNotNode.doRightDeletes; or have doSubnetwork2's delete loop return after
the INSERT/DELETE clash (skip the phantom addDelete) as TupleSetsImpl.addDelete
does. A passing-condition regression test should cover two subnetwork nots in
STREAM mode.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]