Uploaded image for project: 'Red Hat Decision Manager'
  1. Red Hat Decision Manager
  2. RHDM-1629

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

    XMLWordPrintable

Details

    • Bug
    • Status: Verified (View Workflow)
    • Major
    • Resolution: Done
    • 7.10.0.GA
    • 7.11.0.GA
    • BRE
    • Reported environment is RHDM 7.9.0.GA where rules are built and executed with executable model disabled.

      In plain drl, the issue occurs on the releases from RHDM 7.1.0 to 7.10.0.GA.
      In executable model, the issue does not occur.

    • CR1
    • Hide
      1. Extract reproducer.
        $ unzip reproducer_mt_1a.zip
        $ cd reproducer_mt_1a
        
      2. Build and execute the rule on a machine with many cpu/cores.
        $ ./run_mvn
        

        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_mt_1a.zip $ cd reproducer_mt_1a Build and execute the rule on a machine with many cpu/cores. $ ./run_mvn 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.
    • 1
    • 2021 Week 10-12 (from Mar 8)
    • +

    Description

      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
      

      Attachments

        Issue Links

          Activity

            People

              rhn-support-tkobayas Toshiya Kobayashi
              rhn-support-myoshida Masato Yoshida
              Daniel Rosa Daniel Rosa
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: