[jboss-jira] [JBoss JIRA] (DROOLS-1359) Race condition in MVELDialectRuntimeData.getParserConfiguration

Matteo Mortari (JIRA) issues at jboss.org
Wed Nov 16 05:08:00 EST 2016


    [ https://issues.jboss.org/browse/DROOLS-1359?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13323492#comment-13323492 ] 

Matteo Mortari commented on DROOLS-1359:
----------------------------------------

Hi [~chp-anujs], thank you for this; I've checked your reproducer but rewriting it using the public Kie API, and simulating the race condition inside {{MVELDialectRuntimeData}}, does not exhibit the problem, because at build time and during initialization of a new KieSession (either from KieContainer or KieBase) +the public Kie API+ guarantees the thread safety.

Below your test case modified to use the public Kie API (is just one possible example to use the public Kie API)
{code:java}
    @Test
    public void testRaceCondition() {

        List<String> lines = new ArrayList<>();
        lines.add("package testrules");
        lines.add("import static " + Helper.class.getCanonicalName() + ".* ");
        lines.add("import " + Fact.class.getCanonicalName());
        lines.add("rule \"test-rule\" ");
        lines.add("  when ");
        lines.add("    fact : Fact( staticMethod(arg) )");
        lines.add("  then ");
        lines.add("    fact.setActivated(); ");
        lines.add("end");
        String drl = lines.stream().collect(Collectors.joining("\n"));

        KieServices ks = KieServices.Factory.get();
        KieRepository kr = ks.getRepository();
        KieFileSystem kfs = ks.newKieFileSystem();

        kfs.write("src/main/resources/DROOLS-1359.drl", drl);

        KieBuilder kb = ks.newKieBuilder(kfs);
        
        System.out.println("building...");
        kb.buildAll();
        if (kb.getResults().hasMessages(Level.ERROR)) {
            throw new RuntimeException("Build Errors:\n" + kb.getResults().toString());
        }
        System.out.println("building finished.");

        KieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId());
        KieBase knowledgeBase = kContainer.getKieBase();

      int numberOfThreads = 2;

      System.out.println("Starting threads...");
      ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
      Callable<Boolean> executeRulesTask = new Callable<Boolean>() {
        @Override
        public Boolean call() throws Exception {

          // Create a knowledge session
          KieSession session = knowledgeBase.newKieSession();
          try {
            // Insert the fact objects
            session.insert(new Fact());

            // Run the session
            session.fireAllRules();

            return true;
          } catch (RuntimeException e) {
            e.printStackTrace();
            return false;
          } finally {
            session.dispose();
          }
        }
      };

      List<Future<Boolean>> executionResults = new ArrayList<>();

      for (int i = 0; i < numberOfThreads; i++)
        executionResults.add(executor.submit(executeRulesTask));

      executor.shutdown();

      boolean finalResult = true;
      for (int i = 0; i < numberOfThreads; i++) {
        try {
          finalResult &= executionResults.get(i).get();
        } catch (InterruptedException | ExecutionException e) {
          finalResult = false;
        }
      }
      assertTrue(finalResult);
    }
...
public class Helper {
    public static boolean staticMethod(String arg) {
      return true;
    }
  }
...
public class Fact {
        public String getArg() {
          return null;
        }

        public void setActivated() {

        }
      }
{code}
and the {{MVELDialectRuntimeData}} quick modification to attempt the raise of the race-condition (Line 318):
{code:java}
            this.parserConfiguration = new ParserConfiguration();
            try {
                System.out.println("X");
                Thread.sleep(2_000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.parserConfiguration.setImports( this.imports );
            this.parserConfiguration.setPackageImports( this.packageImports );
            this.parserConfiguration.setClassLoader( packageClassLoader );
{code}

In conclusion: not a bug, using the public Kie API does not exhibit racing-condition issues. If you still think there are some issues with the public Kie API, kindly let us know, and thank you anyway for your report so far!

> Race condition in MVELDialectRuntimeData.getParserConfiguration
> ---------------------------------------------------------------
>
>                 Key: DROOLS-1359
>                 URL: https://issues.jboss.org/browse/DROOLS-1359
>             Project: Drools
>          Issue Type: Bug
>          Components: core engine
>    Affects Versions: 5.5.0.Final, 6.5.0.Final
>            Reporter: Anuj Shah
>            Assignee: Mario Fusco
>
> MVELDialectRuntimeData attempts to hold a lazy loaded ParserConfiguration. The getParserConfiguration method sets this to a new configuration object and then sets the imports on the configuration. Between these two steps another thread could retrieve the stale configuration and use it. This could result in a number of exceptions in compilation.
> A simple fix is to delay assignment of new ParserConfiguration until after the imports are set.



--
This message was sent by Atlassian JIRA
(v7.2.3#72005)


More information about the jboss-jira mailing list