Uploaded image for project: 'Apache Jena'
  1. Apache Jena
  2. JENA-399

Concurrent execution of SPARQL CONSTRUCT statements against the same Inference Model leads to a ConcurrentModificationException

    XMLWordPrintableJSON

Details

    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)

      { toClose.add(interpreter.getContext()); }

      }
      for (Iterator<LPInterpreterContext> i = toClose.iterator(); i.hasNext(); )

      { ((LPTopGoalIterator)i.next()).close(); }

      }
      }

      Attachments

        1. JenaReadLockFailureTest.java
          7 kB
          Stephen Owens

        Activity

          People

            rvesse Rob Vesse
            stephen.owens Stephen Owens
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: