Uploaded image for project: 'camunda BPM'
  1. camunda BPM
  2. CAM-14283

Concurrent access to SAX parser factory fails application deployment

XMLWordPrintable

      Environment (Required on creation):

      • Application server environments with multiple deployments and parallel deployment threads, e.g. WildFly distribution with multiple process application deployments

      Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):

      Application deployment fails irregularly for any of the deployments with a ConcurrentModificationException

      2021-12-21 08:35:18,114 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-4) MSC000001: Failed to start service jboss.deployment.unit."PROD_DEPLOYMENT-war-1.125.67.war".POST_MODULE: org.jboss.msc.service.StartException in service jboss.deployment.unit."PROD_DEPLOYMENT-war-1.125.67.war".POST_MODULE: WFLYSRV0153: Failed to process phase POST_MODULE of deployment "PROD_DEPLOYMENT-war-1.125.67.war"
          at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:183) [wildfly-server-10.1.23.Final-redhat-00001-jbeap-22415.jar:10.1.23.Final-redhat-00001-jbeap-22415]
          at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739) [jboss-msc-1.4.11.Final-redhat-00001.jar:1.4.11.Final-redhat-00001]
          at org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701) [jboss-msc-1.4.11.Final-redhat-00001.jar:1.4.11.Final-redhat-00001]
          at org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559) [jboss-msc-1.4.11.Final-redhat-00001.jar:1.4.11.Final-redhat-00001]
          at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) [jboss-threads-2.3.3.Final-redhat-00001.jar:2.3.3.Final-redhat-00001]
          at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982) [jboss-threads-2.3.3.Final-redhat-00001.jar:2.3.3.Final-redhat-00001]
          at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486) [jboss-threads-2.3.3.Final-redhat-00001.jar:2.3.3.Final-redhat-00001]
          at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1363) [jboss-threads-2.3.3.Final-redhat-00001.jar:2.3.3.Final-redhat-00001]
          at java.lang.Thread.run(Thread.java:748) [rt.jar:1.8.0_301]
      Caused by: org.camunda.bpm.engine.ProcessEngineException: ENGINE-09003 Could not parse 'vfs:/content/PROD_DEPLOYMENT-war-1.125.67.war/WEB-INF/classes/META-INF/processes.xml'. null
          at org.camunda.bpm.engine.impl.util.EngineUtilLogger.parsingFailureException(EngineUtilLogger.java:50)
          at org.camunda.bpm.engine.impl.util.xml.Parse.execute(Parse.java:164)
          at org.camunda.bpm.container.impl.metadata.DeploymentMetadataParse.execute(DeploymentMetadataParse.java:50)
          at org.camunda.bpm.application.impl.metadata.ProcessesXmlParse.execute(ProcessesXmlParse.java:60)
          at org.camunda.bpm.container.impl.jboss.deployment.processor.ProcessesXmlProcessor.parseProcessesXml(ProcessesXmlProcessor.java:176)
          at org.camunda.bpm.container.impl.jboss.deployment.processor.ProcessesXmlProcessor.deploy(ProcessesXmlProcessor.java:85)
          at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:176) [wildfly-server-10.1.23.Final-redhat-00001-jbeap-22415.jar:10.1.23.Final-redhat-00001-jbeap-22415]
          ... 8 more
      Caused by: java.util.ConcurrentModificationException
          at java.util.HashMap$HashIterator.nextNode(HashMap.java:1445) [rt.jar:1.8.0_301]
          at java.util.HashMap$EntryIterator.next(HashMap.java:1479) [rt.jar:1.8.0_301]
          at java.util.HashMap$EntryIterator.next(HashMap.java:1477) [rt.jar:1.8.0_301]
          at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.setFeatures(SAXParserImpl.java:247) [rt.jar:1.8.0_301]
          at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.<init>(SAXParserImpl.java:182) [rt.jar:1.8.0_301]
          at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.<init>(SAXParserImpl.java:123) [rt.jar:1.8.0_301]
          at com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl.newSAXParserImpl(SAXParserFactoryImpl.java:96) [rt.jar:1.8.0_301]
          at com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl.setFeature(SAXParserFactoryImpl.java:134) [rt.jar:1.8.0_301]
          at __redirected.__SAXParserFactory.setFeature(__SAXParserFactory.java:96) [jboss-modules.jar:1.11.0.Final-redhat-00001]
          at org.camunda.bpm.engine.impl.util.xml.Parse.execute(Parse.java:140)
          ... 13 more
      

      Steps to reproduce (Required on creation):

      This is not easy to reproduce as this is based on a concurrent access pattern to a class instance that is not thread-safe. The general scheme here is:

      1. Create multiple process application deployments with a processes.xml each
      2. Place those deployments into the application server, e.g., a WildFly instance
      3. Start the application server

      Observed Behavior (Required on creation):

      Occasionally, one or more deployments fail due to a ConcurrentModificationException.

      Expected behavior (Required on creation):

      All deployments are started successfully.

      Root Cause (Required on prioritization):

      • Upon startup of a process application deployment, the processes.xml file is parsed by the engine
      • Parsing this file is done by a SAXParser that is initialized with certain parser features - see https://github.com/camunda/camunda-bpm-platform/blob/0b6a8f89243c69dd46fd8d5ccb5451f031b305ca/engine/src/main/java/org/camunda/bpm/engine/impl/util/xml/Parse.java#L141-L146
      • The deployments are started by concurrent threads in the application server, accessing the linked code concurrently as well
      • The SAXParserFactory we use is NOT THREAD-SAFE, we reuse the same factory instance created once in the Parser for all threads - created over here and fetched over here
      • Setting features on the same factory instance concurrently can lead to modifying the underlying shared parser features HashMap in one thread while iterating over it in another one, leading to the exception over at java.util.HashMap.HashIterator#nextNode (can be found at HashMap.java line 1445 in JDK8_301).

      Solution Ideas (Optional):

      There are at least two ways of preventing this:

      1. Avoid concurrent access to the code in question, e.g., by synchronizing the initialization code block of the parser factory between threads using Java synchronization
      2. Avoid using the same parser factory instance in multiple threads, e.g., by keeping a parser factory instance per thread using ThreadLocal

      Hints (optional):

      • The issue occurs in all supported JDKs, as far as I can tell

        This is the controller panel for Smart Panels app

              tassilo.weidner Tassilo Weidner
              tobias.metzke Tobias Metzke-Bernstein
              Tassilo Weidner Tassilo Weidner
              Nikola Koevski Nikola Koevski
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved: