Uploaded image for project: 'Drools'
  1. Drools
  2. DROOLS-6067

Calling fireAllRules simultaneously from multiple threads in plain drl sometimes causes MVEL syntax errors.

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • None
    • 7.50.0.Final
    • core engine
    • 2021 Week 10-12 (from Mar 8)
    • 3
    • Hide
      1. Extract reproducer.
        $ unzip reproducer_DROOLS-6067_master.zip
        $ cd reproducer_DROOLS-6067_master
        
      1. Build and execute the rule on a machine with many cpu/cores.
        $ ./run_mvn_master
        

        run_mvn script build with -DgenerateModel=NO and then run the test (*2) 100 times. The output is written to reproducer_mt_1a_output_YYYYMMDDhhmmss.log.txt. You might be able to see (*e1) or (*e2) several times of 100 times.

      Show
      Extract reproducer. $ unzip reproducer_DROOLS-6067_master.zip $ cd reproducer_DROOLS-6067_master Build and execute the rule on a machine with many cpu/cores. $ ./run_mvn_master run_mvn script build with -DgenerateModel=NO and then run the test (*2) 100 times. The output is written to reproducer_mt_1a_output_ YYYYMMDDhhmmss .log.txt . You might be able to see (*e1) or (*e2) several times of 100 times.
    • Undefined
    • NEW
    • NEW
    • ---
    • ---

      When we build a rule written in MVEL dialect like (*1) with executable model disabled and run the rule using the test code like (*2), MVEL syntax error like (*e1) or (*e2) sometimes occurs though the rule normally does not cause errors. The test code simultaneously executes multiple jobs each of which creates a new KieSession, inserts objects and calls fireAllRules.

      (*1)

      package com.example.reproducer
      
      import static com.example.reproducer.Utils.TOSTRING
      
      dialect "mvel"
      
      rule "rule_mt_1a"
          when
              $bus : Bus( $check: "GAMMA RAY",
                          $title: "POWER PLANT",
                          karaoke.dvd[$title] != null,
                          TOSTRING(karaoke.dvd[$title].artist) != null )
          then
              System.out.println("***** $bus: " + $bus + ", $check: " + $check + ", $title: " + $title);
      end
      

      (*2) Test code (In the actual code in the reproducer, java.util.concurrent.Semaphore is used for making reproducibility higher.)

          KieServices kServices = KieServices.Factory.get();
          KieContainer kContainer = kServices.getKieClasspathContainer();
      
          int THREADS = 32;
          int REQUESTS = 10000;
      
          ExecutorService pool = Executors.newFixedThreadPool(THREADS);
          List<Future<?>> fs = new ArrayList<>();
      
          System.out.println("***** start threads");
          for (int i = 0; i < REQUESTS; i++) {
              fs.add(pool.submit(new Runnable() {
                  public void run() {
                      KieSession kSession = kContainer.newKieSession("session1");
      
                      Driver driver = new Driver("Hiroshi");
                      driver.setFavorite("POWER PLANT");
                      kSession.insert(driver);
      
                      Bus bus1 = new Bus("red", 30);
                      bus1.getKaraoke().getDvd().put("POWER PLANT", new Album("POWER PLANT", "GAMMA RAY"));
                      bus1.getKaraoke().getDvd().put("Somewhere Out In Space", new Album("Somewhere Out In Space", "GAMMA RAY"));
                      kSession.insert(bus1);
      
                      try {
                          kSession.fireAllRules();
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
      
                      kSession.dispose();
                      kSession.destroy();
                  }
              }));
          }
      

      (*e1) Error 1

      java.lang.RuntimeException: Error evaluating constraint 'TOSTRING(karaoke.dvd[$title].artist) != null' in [Rule "rule_mt_1a" in /work2/testdir/reproducer_mt_1a/target/classes/com/example/reproducer/Sample.drl]
              at org.drools.mvel.MVELConstraint.evaluate(MVELConstraint.java:278)
              at org.drools.mvel.MVELConstraint.isAllowed(MVELConstraint.java:226)
              at org.drools.core.reteoo.AlphaNode.assertObject(AlphaNode.java:133)
              at org.drools.core.reteoo.SingleObjectSinkAdapter.propagateAssertObject(SingleObjectSinkAdapter.java:70)
              at org.drools.core.reteoo.AlphaNode.assertObject(AlphaNode.java:134)
              at org.drools.core.reteoo.SingleObjectSinkAdapter.propagateAssertObject(SingleObjectSinkAdapter.java:70)
              at org.drools.core.reteoo.ObjectTypeNode.propagateAssert(ObjectTypeNode.java:297)
              at org.drools.core.phreak.PropagationEntry$Insert.propagate(PropagationEntry.java:161)
              at org.drools.core.phreak.PropagationEntry$Insert.execute(PropagationEntry.java:166)
              at org.drools.core.phreak.SynchronizedPropagationList.flush(SynchronizedPropagationList.java:96)
              at org.drools.core.phreak.SynchronizedPropagationList.flush(SynchronizedPropagationList.java:91)
              at org.drools.core.common.DefaultAgenda.fireLoop(DefaultAgenda.java:1095)
              at org.drools.core.common.DefaultAgenda.internalFireAllRules(DefaultAgenda.java:1058)
              at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1050)
              at org.drools.core.impl.StatefulKnowledgeSessionImpl.internalFireAllRules(StatefulKnowledgeSessionImpl.java:1346)
              at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1337)
              at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1321)
              at com.example.reproducer.DroolsTest$1.run(DroolsTest.java:81)
              at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
              at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
              at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
              at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
              at java.base/java.lang.Thread.run(Thread.java:834)
      Caused by: [Error: not a statement, or badly formed structure]
      [Near : {... TOSTRING(karaoke.dvd[$title].artist) != ....}]
                            ^
      [Line: 1, Column: 10]
              at org.mvel2.compiler.ExpressionCompiler._compile(ExpressionCompiler.java:311)
              at org.mvel2.util.ParseTools.subCompileExpression(ParseTools.java:2112)
              at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getMethod(ReflectiveAccessorOptimizer.java:969)
              at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:400)
              at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(ReflectiveAccessorOptimizer.java:167)
              at org.mvel2.ast.ASTNode.optimize(ASTNode.java:159)
              at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:115)
              at org.mvel2.ast.BinaryOperation.getReducedValueAccelerated(BinaryOperation.java:139)
              at org.mvel2.MVELRuntime.execute(MVELRuntime.java:85)
              at org.mvel2.compiler.CompiledExpression.getDirectValue(CompiledExpression.java:123)
              at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:119)
              at org.mvel2.MVEL.executeExpression(MVEL.java:945)
              at org.kie.soup.project.datamodel.commons.util.RawMVELEvaluator.executeExpression(RawMVELEvaluator.java:103)
              at org.drools.mvel.MVELConditionEvaluator.evaluate(MVELConditionEvaluator.java:112)
              at org.drools.mvel.MVELConditionEvaluator.evaluate(MVELConditionEvaluator.java:88)
              at org.drools.mvel.MVELConstraint.evaluate(MVELConstraint.java:276)
              ... 22 more
      Caused by: java.lang.NullPointerException
              at org.mvel2.compiler.PropertyVerifier.getCollectionProperty(PropertyVerifier.java:403)
              at org.mvel2.compiler.PropertyVerifier.analyze(PropertyVerifier.java:139)
              at org.mvel2.compiler.ExpressionCompiler.verify(ExpressionCompiler.java:399)
              at org.mvel2.compiler.ExpressionCompiler._compile(ExpressionCompiler.java:281)
              ... 37 more
      

      (*e2) Error 2

      java.lang.RuntimeException: Error evaluating constraint 'TOSTRING(karaoke.dvd[$title].artist) != null' in [Rule "rule_mt_1a" in /work2/testdir/reproducer_mt_1a/target/classes/com/example/reproducer/Sample.drl]
              at org.drools.mvel.MVELConstraint.evaluate(MVELConstraint.java:278)
              at org.drools.mvel.MVELConstraint.isAllowed(MVELConstraint.java:226)
              at org.drools.core.reteoo.AlphaNode.assertObject(AlphaNode.java:133)
              at org.drools.core.reteoo.SingleObjectSinkAdapter.propagateAssertObject(SingleObjectSinkAdapter.java:70)
              at org.drools.core.reteoo.AlphaNode.assertObject(AlphaNode.java:134)
              at org.drools.core.reteoo.SingleObjectSinkAdapter.propagateAssertObject(SingleObjectSinkAdapter.java:70)
              at org.drools.core.reteoo.ObjectTypeNode.propagateAssert(ObjectTypeNode.java:297)
              at org.drools.core.phreak.PropagationEntry$Insert.propagate(PropagationEntry.java:161)
              at org.drools.core.phreak.PropagationEntry$Insert.execute(PropagationEntry.java:166)
              at org.drools.core.phreak.SynchronizedPropagationList.flush(SynchronizedPropagationList.java:96)
              at org.drools.core.phreak.SynchronizedPropagationList.flush(SynchronizedPropagationList.java:91)
              at org.drools.core.common.DefaultAgenda.fireLoop(DefaultAgenda.java:1095)
              at org.drools.core.common.DefaultAgenda.internalFireAllRules(DefaultAgenda.java:1058)
              at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1050)
              at org.drools.core.impl.StatefulKnowledgeSessionImpl.internalFireAllRules(StatefulKnowledgeSessionImpl.java:1346)
              at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1337)
              at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1321)
              at com.example.reproducer.DroolsTest$1.run(DroolsTest.java:81)
              at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
              at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
              at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
              at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
              at java.base/java.lang.Thread.run(Thread.java:834)
      Caused by: [Error: unable to resolve method using strict-mode: java.lang.Object.artist()]
      [Near : {... TOSTRING(karaoke.dvd[$title].artist) != null ....}]
                                                ^
      [Line: 1, Column: 30]
              at org.mvel2.compiler.PropertyVerifier.getMethod(PropertyVerifier.java:581)
              at org.mvel2.compiler.PropertyVerifier.getBeanProperty(PropertyVerifier.java:295)
              at org.mvel2.compiler.PropertyVerifier.analyze(PropertyVerifier.java:133)
              at org.mvel2.compiler.ExpressionCompiler.verify(ExpressionCompiler.java:399)
              at org.mvel2.compiler.ExpressionCompiler._compile(ExpressionCompiler.java:281)
              at org.mvel2.util.ParseTools.subCompileExpression(ParseTools.java:2112)
              at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getMethod(ReflectiveAccessorOptimizer.java:969)
              at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:400)
              at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(ReflectiveAccessorOptimizer.java:167)
              at org.mvel2.ast.ASTNode.optimize(ASTNode.java:159)
              at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:115)
              at org.mvel2.ast.BinaryOperation.getReducedValueAccelerated(BinaryOperation.java:139)
              at org.mvel2.MVELRuntime.execute(MVELRuntime.java:85)
              at org.mvel2.compiler.CompiledExpression.getDirectValue(CompiledExpression.java:123)
              at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:119)
              at org.mvel2.MVEL.executeExpression(MVEL.java:945)
              at org.kie.soup.project.datamodel.commons.util.RawMVELEvaluator.executeExpression(RawMVELEvaluator.java:103)
              at org.drools.mvel.MVELConditionEvaluator.evaluate(MVELConditionEvaluator.java:112)
              at org.drools.mvel.MVELConditionEvaluator.evaluate(MVELConditionEvaluator.java:88)
              at org.drools.mvel.MVELConstraint.evaluate(MVELConstraint.java:276)
              ... 22 more
      

              rhn-support-tkobayas Toshiya Kobayashi
              rhn-support-tkobayas Toshiya Kobayashi
              Daniel Rosa Daniel Rosa
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated:
                Resolved: