[
https://issues.apache.org/jira/browse/JENA-904?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14372462#comment-14372462
]
Stian Soiland-Reyes commented on JENA-904:
------------------------------------------
I fixed this by ensuring all .close() did call super.close() and for
ConsumerChoicePointFrame calling generator.interpreter.close()
See pull request #46 https://github.com/apache/jena/pull/46
> LPBRuleEngine leaks activeInterpreters
> --------------------------------------
>
> Key: JENA-904
> URL: https://issues.apache.org/jira/browse/JENA-904
> Project: Apache Jena
> Issue Type: Bug
> Components: Ontology API
> Reporter: Stian Soiland-Reyes
>
> I found that activeInterpreters in LPBRuleEngine leaks also if you don't
> iterate through to the end - calling .close() on the iterator is not enough.
> Clean-up seems to only happen when it.hasNext() is called and it returns
> false - so this could happen also in cases like where you return after
> getting the first hit.
> {code}
> @Test
> public void testNotLeakingActiveInterpreters() throws Exception {
> Graph data = Factory.createGraphMem();
> data.add(new Triple(a, ty, C1));
> data.add(new Triple(b, ty, C1));
> List<Rule> rules = Rule
> .parseRules("[r1: (?x p ?t) <- (?x rdf:type
> C1), makeInstance(?x, p, C2, ?t)]"
> + "[r2: (?t rdf:type C2) <-
> (?x rdf:type C1), makeInstance(?x, p, C2, ?t)]");
> FBRuleInfGraph infgraph = (FBRuleInfGraph)
> createReasoner(rules).bind(
> data);
> LPBRuleEngine engine = getEngineForGraph(infgraph);
> assertEquals(0, engine.activeInterpreters.size());
> assertEquals(0, engine.tabledGoals.size());
> // we ask for a non-hit -- it works, but only because we call
> it.hasNext()
> ExtendedIterator<Triple> it = infgraph.find(nohit, ty, C1);
> assertFalse(it.hasNext());
> it.close();
> assertEquals(0, engine.activeInterpreters.size());
> // and again.
> // Ensure this is not cached by asking for a different triple
> pattern
> ExtendedIterator<Triple> it2 = infgraph.find(nohit, ty, C2);
> // uuups, forgot to call it.hasNext(). But .close() should tidy
> it2.close();
> assertEquals(0, engine.activeInterpreters.size());
>
> // OK, let's ask for something that is in the graph
>
> ExtendedIterator<Triple> it3 = infgraph.find(a, ty, C1);
> assertTrue(it3.hasNext());
> assertEquals(a, it3.next().getMatchSubject());
>
> // .. and what if we forget to call next() to consume b?
> // (e.g. return from a method with the first hit)
>
> // this should be enough
> it3.close();
> // without leaks of activeInterpreters
> assertEquals(0, engine.activeInterpreters.size());
> }
> {code}
> When investigating this, I got as far as seeing that the activeInterpreters
> is normally closed from hasNext() when it reaches the end here:
> https://github.com/apache/jena/blob/master/jena-core/src/main/java/com/hp/hpl/jena/reasoner/rulesys/impl/Generator.java#L303
> which is a zombie check.. but this doesn't work when hasNext() hasn't reach
> the end, even though it is also called from close() here:
> https://github.com/apache/jena/blob/master/jena-core/src/main/java/com/hp/hpl/jena/reasoner/rulesys/impl/LPTopGoalIterator.java#L199
> Moving the checkForCompletions further down and calling .close() on any
> nextToRun or lookAhead was not sufficient - there is always a secondary
> Generator in the list which is not removed - only the top-level one is
> removed normally.
> I was unable to investigate any further as I could not understand the classes
> that were creating the two Generators.
> The inner LPInterpreter 147 is first created from generatorFor() call from
> ConsumerChoicePointFrame constructor within LPInterpreter.setupTabledCall
> which is coming from the ruleEngine.find.
> This outer LPInterpreter is then added as part of the find().
> In "normal operation" the inner one is removed through the zombie clearing,
> while the outer one is removed through .close()
> If you don't iterate through to the end, the inner one is not removed.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)