Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Done
-
Jena 2.10.0
Description
Read lock seems to be insufficient for a construct SPARQL query against a model in a multi-threaded situation. See the attached test case for details.
The ConcurrentModificationException is thrown from: LPTopGoalIterator.checkClosed
in com.hp.hpl.jena.reasoner.rulesys.impl.LPTopGoalIterator
Here is a stack trace that shows a path from QueryExecutionBase.
execConstruct() to LPBRuleEngine.checkSafeToUpdate():
LPBRuleEngine.checkSafeToUpdate() line: 223
LPBRuleEngine.deleteAllRules() line: 155
RDFSRuleInfGraph(FBRuleInfGraph).prepare() line: 460
RDFSRuleInfGraph(FBRuleInfGraph).findWithContinuation(TriplePattern, Finder) line: 573
RDFSRuleInfGraph(FBRuleInfGraph).graphBaseFind(Node, Node, Node) line: 605
RDFSRuleInfGraph(GraphBase).find(Node, Node, Node) line: 287
QueryIterTriplePattern$TripleMapper.<init>(Binding, Triple, ExecutionContext) line: 80
QueryIterTriplePattern.nextStage(Binding) line: 53
QueryIterTriplePattern(QueryIterRepeatApply).makeNextStage() line: 115
QueryIterTriplePattern(QueryIterRepeatApply).hasNextBinding() line: 67
QueryIterTriplePattern(QueryIteratorBase).hasNext() line: 113
QueryIterBlockTriples.hasNextBinding() line: 64
QueryIterBlockTriples(QueryIteratorBase).hasNext() line: 113
QueryIterOptionalIndex(QueryIterRepeatApply).makeNextStage() line: 108
QueryIterOptionalIndex(QueryIterRepeatApply).hasNextBinding() line: 67
QueryIterOptionalIndex(QueryIteratorBase).hasNext() line: 113
QueryIteratorCheck(QueryIteratorWrapper).hasNextBinding() line: 40
QueryIteratorCheck(QueryIteratorBase).hasNext() line: 113
QueryIteratorCloseable(QueryIteratorWrapper).hasNextBinding() line: 40
QueryIteratorCloseable(QueryIteratorBase).hasNext() line: 113
Iter$5.hasNext() line: 335
QueryExecutionBase.execConstruct(Model) line: 225
QueryExecutionBase.execConstruct() line: 201
This is a problem because LPBRuleEngine.checkSafeToUpdate() closes all LPTopGoalIterator iterators, some of which are in the middle of processing:
public void checkSafeToUpdate() {
if (!activeInterpreters.isEmpty()) {
ArrayList<LPInterpreterContext> toClose = new ArrayList<LPInterpreterContext>();
for (Iterator<LPInterpreter> i = activeInterpreters.iterator(); i.hasNext(); ) {
LPInterpreter interpreter = i.next();
if (interpreter.getContext() instanceof LPTopGoalIterator)
}
for (Iterator<LPInterpreterContext> i = toClose.iterator(); i.hasNext(); )
}
}