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

Sending signal can cause unexpected NPE in race condition

      Environment (Required on creation):

      Tested with 7.17 spring boot, likely happens with other versions, too.

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

      If we send a signal to an execution that exists at the time of sending but finishes just after we've sent the signal then the send method will throw a NullPointerException. This can cause failures in client applications as they don't expect a NPE here.

      Steps to reproduce (Required on creation):

      As this only happens in a race condition, the easiest to reproduce this is in an IDE with breakpoints.
      Start two processes simultaneously, have a user task in both so they don't finish immediately. One of the process needs to have a step after the user task where it sends a signal to the other one. Right after the signal send was called, the other execution should finish --> To achieve this, the simplest is to set a breakpoint in the SignalEventReceivedCmd.sendSignalToExecution() method at the line of checkAuthorizationOfCatchSignals then we finish the other process' user task and finally we let go the suspended other process.
      The send method will throw a NPE.

      There is a complete example in the support ticket.

      Observed Behavior (Required on creation):

      The send throws a NPE.

      Expected behavior (Required on creation):

      It shouldn't throw a NPE.

      Root Cause (Required on prioritization):

      Problem seems to be that both `ExecutionEntity.ensureExecutionsInitialized` and `ExecutionEntity.ensureExecutionTreeInitialized` aren't initializing the executions, leaving it null. Which kind of make sense, since the execution had already finished but still the method names suggest that they should in fact ensure it is initialized.

      This is the exception being thrown:

      java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "children" is null
          at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.getNonEventScopeExecutions(PvmExecutionImpl.java:1098)
          at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createConcurrentExecution(PvmExecutionImpl.java:527)
      

      Solution Ideas (Optional):

      How should the method send end in this case:

      Hints (optional):

        This is the controller panel for Smart Panels app

            [CAM-14740] Sending signal can cause unexpected NPE in race condition

            Daniel Kelemen created issue -
            Daniel Kelemen made changes -
            Description Original: h3. Environment (Required on creation):

            Tested with 7.17 spring boot, likely happens with other versions, too.
             
                h3. Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):

            If we send a signal to an execution that exists at the time of sending but finishes just after we've sent the signal then the send method will throw a NullPointerException. This can cause failures in client applications as they don't expect a NPE here.
             
                h3. Steps to reproduce (Required on creation):

            As this only happens in a race condition, the easiest to reproduce this is in an IDE with breakpoints.
            Start two processes simultaneously, have a user task in both so they don't finish immediately. One of the process needs to have a step after the user task where it sends a signal to the other one. Right after the signal was sent, the other execution should finish --> To achieve this, the simplest is to set a breakpoint in the {{SignalEventReceivedCmd.sendSignalToExecution()}} method at the line of {{checkAuthorizationOfCatchSignals}} then we finish the other process' user task and finally we let go the suspended other process.
            The {{send}} method will throw a NPE.

            There is a complete example in the support ticket.
                
                h3. Observed Behavior (Required on creation):

            The {{send}} throws a NPE.
                
                h3. Expected behavior (Required on creation):

            It shouldn't throw a NPE.
                
                h3. Root Cause (Required on prioritization):

            Problem seems to be that both `ExecutionEntity.ensureExecutionsInitialized` and `ExecutionEntity.ensureExecutionTreeInitialized` aren't initializing the executions, leaving it {{null}}. Which kind of make sense, since the execution had already finished but still the method names suggest that they should in fact _ensure it is initialized_.

            This is the exception being thrown:
            {code}
            java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "children" is null
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.getNonEventScopeExecutions(PvmExecutionImpl.java:1098)
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createConcurrentExecution(PvmExecutionImpl.java:527)
            {code}
                
                h3. Solution Ideas (Optional):

            How should the method send end in this case:
            - throw a {{NullValueException}}? This is what happens if the execution is missing at the time of invoking the send signal. It would make sense and it is something that a developer would expect and handle.
            - silently complete/do nothing. It was the suggestion from the customer. At the point of calling the send, the execution is present but later on during the execution it finishes.
                
                h3. Hints (optional):
            New: h3. Environment (Required on creation):

            Tested with 7.17 spring boot, likely happens with other versions, too.
             
                h3. Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):

            If we send a signal to an execution that exists at the time of sending but finishes just after we've sent the signal then the send method will throw a NullPointerException. This can cause failures in client applications as they don't expect a NPE here.
             
                h3. Steps to reproduce (Required on creation):

            As this only happens in a race condition, the easiest to reproduce this is in an IDE with breakpoints.
            Start two processes simultaneously, have a user task in both so they don't finish immediately. One of the process needs to have a step after the user task where it sends a signal to the other one. Right after the signal was sent, the other execution should finish --> To achieve this, the simplest is to set a breakpoint in the {{SignalEventReceivedCmd.sendSignalToExecution()}} method at the line of {{checkAuthorizationOfCatchSignals}} then we finish the other process' user task and finally we let go the suspended other process.
            The {{send}} method will throw a NPE.

            There is a complete example in the support ticket.
                
                h3. Observed Behavior (Required on creation):

            The {{send}} throws a NPE.
                
                h3. Expected behavior (Required on creation):

            It shouldn't throw a NPE.
                
                h3. Root Cause (Required on prioritization):

            Problem seems to be that both `ExecutionEntity.ensureExecutionsInitialized` and `ExecutionEntity.ensureExecutionTreeInitialized` aren't initializing the executions, leaving it {{null}}. Which kind of make sense, since the execution had already finished but still the method names suggest that they should in fact _ensure it is initialized_.

            This is the exception being thrown:
            {code}
            java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "children" is null
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.getNonEventScopeExecutions(PvmExecutionImpl.java:1098)
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createConcurrentExecution(PvmExecutionImpl.java:527)
            {code}
                
                h3. Solution Ideas (Optional):

            How should the method send end in this case:
            - throw a {{NullValueException}}? This is what happens if the execution is missing at the time of invoking the send signal. It would make sense and it is something that a developer would expect and handle.
            - silently complete/do nothing. It was the suggestion from the customer. At the point of calling the send, the execution is present but later on during the execution it finishes. This could potentially cause confusions as to what happened: "no exception but the other process still didn't received the signal?"
                
                h3. Hints (optional):
            Daniel Kelemen made changes -
            Assignee New: Thorben Lindhauer [ thorben.lindhauer ]
            Daniel Kelemen made changes -
            Description Original: h3. Environment (Required on creation):

            Tested with 7.17 spring boot, likely happens with other versions, too.
             
                h3. Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):

            If we send a signal to an execution that exists at the time of sending but finishes just after we've sent the signal then the send method will throw a NullPointerException. This can cause failures in client applications as they don't expect a NPE here.
             
                h3. Steps to reproduce (Required on creation):

            As this only happens in a race condition, the easiest to reproduce this is in an IDE with breakpoints.
            Start two processes simultaneously, have a user task in both so they don't finish immediately. One of the process needs to have a step after the user task where it sends a signal to the other one. Right after the signal was sent, the other execution should finish --> To achieve this, the simplest is to set a breakpoint in the {{SignalEventReceivedCmd.sendSignalToExecution()}} method at the line of {{checkAuthorizationOfCatchSignals}} then we finish the other process' user task and finally we let go the suspended other process.
            The {{send}} method will throw a NPE.

            There is a complete example in the support ticket.
                
                h3. Observed Behavior (Required on creation):

            The {{send}} throws a NPE.
                
                h3. Expected behavior (Required on creation):

            It shouldn't throw a NPE.
                
                h3. Root Cause (Required on prioritization):

            Problem seems to be that both `ExecutionEntity.ensureExecutionsInitialized` and `ExecutionEntity.ensureExecutionTreeInitialized` aren't initializing the executions, leaving it {{null}}. Which kind of make sense, since the execution had already finished but still the method names suggest that they should in fact _ensure it is initialized_.

            This is the exception being thrown:
            {code}
            java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "children" is null
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.getNonEventScopeExecutions(PvmExecutionImpl.java:1098)
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createConcurrentExecution(PvmExecutionImpl.java:527)
            {code}
                
                h3. Solution Ideas (Optional):

            How should the method send end in this case:
            - throw a {{NullValueException}}? This is what happens if the execution is missing at the time of invoking the send signal. It would make sense and it is something that a developer would expect and handle.
            - silently complete/do nothing. It was the suggestion from the customer. At the point of calling the send, the execution is present but later on during the execution it finishes. This could potentially cause confusions as to what happened: "no exception but the other process still didn't received the signal?"
                
                h3. Hints (optional):
            New: h3. Environment (Required on creation):

            Tested with 7.17 spring boot, likely happens with other versions, too.
             
                h3. Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):

            If we send a signal to an execution that exists at the time of sending but finishes just after we've sent the signal then the send method will throw a NullPointerException. This can cause failures in client applications as they don't expect a NPE here.
             
                h3. Steps to reproduce (Required on creation):

            As this only happens in a race condition, the easiest to reproduce this is in an IDE with breakpoints.
            Start two processes simultaneously, have a user task in both so they don't finish immediately. One of the process needs to have a step after the user task where it sends a signal to the other one. Right after the signal {{send}} was called, the other execution should finish --> To achieve this, the simplest is to set a breakpoint in the {{SignalEventReceivedCmd.sendSignalToExecution()}} method at the line of {{checkAuthorizationOfCatchSignals}} then we finish the other process' user task and finally we let go the suspended other process.
            The {{send}} method will throw a NPE.

            There is a complete example in the support ticket.
                
                h3. Observed Behavior (Required on creation):

            The {{send}} throws a NPE.
                
                h3. Expected behavior (Required on creation):

            It shouldn't throw a NPE.
                
                h3. Root Cause (Required on prioritization):

            Problem seems to be that both `ExecutionEntity.ensureExecutionsInitialized` and `ExecutionEntity.ensureExecutionTreeInitialized` aren't initializing the executions, leaving it {{null}}. Which kind of make sense, since the execution had already finished but still the method names suggest that they should in fact _ensure it is initialized_.

            This is the exception being thrown:
            {code}
            java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "children" is null
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.getNonEventScopeExecutions(PvmExecutionImpl.java:1098)
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createConcurrentExecution(PvmExecutionImpl.java:527)
            {code}
                
                h3. Solution Ideas (Optional):

            How should the method send end in this case:
            - throw a {{NullValueException}}? This is what happens if the execution is missing at the time of invoking the send signal. It would make sense and it is something that a developer would expect and handle.
            - silently complete/do nothing. It was the suggestion from the customer. At the point of calling the send, the execution is present but later on during the execution it finishes. This could potentially cause confusions as to what happened: "no exception but the other process still didn't received the signal?"
                
                h3. Hints (optional):
            Garima Yadav made changes -
            Link New: This issue is related to SUPPORT-13932 [ SUPPORT-13932 ]
            Thorben Lindhauer made changes -
            Description Original: h3. Environment (Required on creation):

            Tested with 7.17 spring boot, likely happens with other versions, too.
             
                h3. Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):

            If we send a signal to an execution that exists at the time of sending but finishes just after we've sent the signal then the send method will throw a NullPointerException. This can cause failures in client applications as they don't expect a NPE here.
             
                h3. Steps to reproduce (Required on creation):

            As this only happens in a race condition, the easiest to reproduce this is in an IDE with breakpoints.
            Start two processes simultaneously, have a user task in both so they don't finish immediately. One of the process needs to have a step after the user task where it sends a signal to the other one. Right after the signal {{send}} was called, the other execution should finish --> To achieve this, the simplest is to set a breakpoint in the {{SignalEventReceivedCmd.sendSignalToExecution()}} method at the line of {{checkAuthorizationOfCatchSignals}} then we finish the other process' user task and finally we let go the suspended other process.
            The {{send}} method will throw a NPE.

            There is a complete example in the support ticket.
                
                h3. Observed Behavior (Required on creation):

            The {{send}} throws a NPE.
                
                h3. Expected behavior (Required on creation):

            It shouldn't throw a NPE.
                
                h3. Root Cause (Required on prioritization):

            Problem seems to be that both `ExecutionEntity.ensureExecutionsInitialized` and `ExecutionEntity.ensureExecutionTreeInitialized` aren't initializing the executions, leaving it {{null}}. Which kind of make sense, since the execution had already finished but still the method names suggest that they should in fact _ensure it is initialized_.

            This is the exception being thrown:
            {code}
            java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "children" is null
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.getNonEventScopeExecutions(PvmExecutionImpl.java:1098)
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createConcurrentExecution(PvmExecutionImpl.java:527)
            {code}
                
                h3. Solution Ideas (Optional):

            How should the method send end in this case:
            - throw a {{NullValueException}}? This is what happens if the execution is missing at the time of invoking the send signal. It would make sense and it is something that a developer would expect and handle.
            - silently complete/do nothing. It was the suggestion from the customer. At the point of calling the send, the execution is present but later on during the execution it finishes. This could potentially cause confusions as to what happened: "no exception but the other process still didn't received the signal?"
                
                h3. Hints (optional):
            New: h3. Environment (Required on creation):

            Tested with 7.17 spring boot, likely happens with other versions, too.
             
                h3. Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):

            If we send a signal to an execution that exists at the time of sending but finishes just after we've sent the signal then the send method will throw a NullPointerException. This can cause failures in client applications as they don't expect a NPE here.
             
                h3. Steps to reproduce (Required on creation):

            As this only happens in a race condition, the easiest to reproduce this is in an IDE with breakpoints.
            Start two processes simultaneously, have a user task in both so they don't finish immediately. One of the process needs to have a step after the user task where it sends a signal to the other one. Right after the signal {{send}} was called, the other execution should finish --> To achieve this, the simplest is to set a breakpoint in the {{SignalEventReceivedCmd.sendSignalToExecution()}} method at the line of {{checkAuthorizationOfCatchSignals}} then we finish the other process' user task and finally we let go the suspended other process.
            The {{send}} method will throw a NPE.

            There is a complete example in the support ticket.
                
                h3. Observed Behavior (Required on creation):

            The {{send}} throws a NPE.
                
                h3. Expected behavior (Required on creation):

            It shouldn't throw a NPE.
                
                h3. Root Cause (Required on prioritization):

            Problem seems to be that both `ExecutionEntity.ensureExecutionsInitialized` and `ExecutionEntity.ensureExecutionTreeInitialized` aren't initializing the executions, leaving it {{null}}. Which kind of make sense, since the execution had already finished but still the method names suggest that they should in fact _ensure it is initialized_.

            This is the exception being thrown:
            {code}
            java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "children" is null
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.getNonEventScopeExecutions(PvmExecutionImpl.java:1098)
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createConcurrentExecution(PvmExecutionImpl.java:527)
            {code}
                
                h3. Solution Ideas (Optional):

            How should the method send end in this case:
            - throw a {{NullValueException}} when the engine detects the inconsistency that the executions have already been deleted (i.e. add validation to {{ExecutionEntity#restoreProcessInstance}} that checks that the process instance execution is in the list of executions passed in). This behavior is similar to when the signal method is called with an execution id that does not exist
                
                h3. Hints (optional):
            Thorben Lindhauer made changes -
            Fix Version/s New: 7.17.x [ 17395 ]
            Fix Version/s New: 7.18.0 [ 17394 ]
            Thorben Lindhauer made changes -
            Description Original: h3. Environment (Required on creation):

            Tested with 7.17 spring boot, likely happens with other versions, too.
             
                h3. Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):

            If we send a signal to an execution that exists at the time of sending but finishes just after we've sent the signal then the send method will throw a NullPointerException. This can cause failures in client applications as they don't expect a NPE here.
             
                h3. Steps to reproduce (Required on creation):

            As this only happens in a race condition, the easiest to reproduce this is in an IDE with breakpoints.
            Start two processes simultaneously, have a user task in both so they don't finish immediately. One of the process needs to have a step after the user task where it sends a signal to the other one. Right after the signal {{send}} was called, the other execution should finish --> To achieve this, the simplest is to set a breakpoint in the {{SignalEventReceivedCmd.sendSignalToExecution()}} method at the line of {{checkAuthorizationOfCatchSignals}} then we finish the other process' user task and finally we let go the suspended other process.
            The {{send}} method will throw a NPE.

            There is a complete example in the support ticket.
                
                h3. Observed Behavior (Required on creation):

            The {{send}} throws a NPE.
                
                h3. Expected behavior (Required on creation):

            It shouldn't throw a NPE.
                
                h3. Root Cause (Required on prioritization):

            Problem seems to be that both `ExecutionEntity.ensureExecutionsInitialized` and `ExecutionEntity.ensureExecutionTreeInitialized` aren't initializing the executions, leaving it {{null}}. Which kind of make sense, since the execution had already finished but still the method names suggest that they should in fact _ensure it is initialized_.

            This is the exception being thrown:
            {code}
            java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "children" is null
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.getNonEventScopeExecutions(PvmExecutionImpl.java:1098)
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createConcurrentExecution(PvmExecutionImpl.java:527)
            {code}
                
                h3. Solution Ideas (Optional):

            How should the method send end in this case:
            - throw a {{NullValueException}} when the engine detects the inconsistency that the executions have already been deleted (i.e. add validation to {{ExecutionEntity#restoreProcessInstance}} that checks that the process instance execution is in the list of executions passed in). This behavior is similar to when the signal method is called with an execution id that does not exist
                
                h3. Hints (optional):
            New: h3. Environment (Required on creation):

            Tested with 7.17 spring boot, likely happens with other versions, too.
             
                h3. Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):

            If we send a signal to an execution that exists at the time of sending but finishes just after we've sent the signal then the send method will throw a NullPointerException. This can cause failures in client applications as they don't expect a NPE here.
             
                h3. Steps to reproduce (Required on creation):

            As this only happens in a race condition, the easiest to reproduce this is in an IDE with breakpoints.
            Start two processes simultaneously, have a user task in both so they don't finish immediately. One of the process needs to have a step after the user task where it sends a signal to the other one. Right after the signal {{send}} was called, the other execution should finish --> To achieve this, the simplest is to set a breakpoint in the {{SignalEventReceivedCmd.sendSignalToExecution()}} method at the line of {{checkAuthorizationOfCatchSignals}} then we finish the other process' user task and finally we let go the suspended other process.
            The {{send}} method will throw a NPE.

            There is a complete example in the support ticket.
                
                h3. Observed Behavior (Required on creation):

            The {{send}} throws a NPE.
                
                h3. Expected behavior (Required on creation):

            It shouldn't throw a NPE.
                
                h3. Root Cause (Required on prioritization):

            Problem seems to be that both `ExecutionEntity.ensureExecutionsInitialized` and `ExecutionEntity.ensureExecutionTreeInitialized` aren't initializing the executions, leaving it {{null}}. Which kind of make sense, since the execution had already finished but still the method names suggest that they should in fact _ensure it is initialized_.

            This is the exception being thrown:
            {code}
            java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "children" is null
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.getNonEventScopeExecutions(PvmExecutionImpl.java:1098)
                at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createConcurrentExecution(PvmExecutionImpl.java:527)
            {code}
                
                h3. Solution Ideas (Optional):

            How should the method send end in this case:
            - throw a {{NullValueException}} when the engine detects the inconsistency that the executions have already been deleted (i.e. add validation to {{ExecutionEntity#restoreProcessInstance}} (https://github.com/camunda/camunda-bpm-platform/blob/7.17.0/engine/src/main/java/org/camunda/bpm/engine/impl/persistence/entity/ExecutionEntity.java#L1307-L1313) that checks that the process instance execution is in the list of executions passed in). This behavior is similar to when the signal method is called with an execution id that does not exist
                
                h3. Hints (optional):
            Thorben Lindhauer made changes -
            Remote Link New: This issue links to "Page (camunda confluence)" [ 17565 ]
            Thorben Lindhauer made changes -
            Assignee Original: Thorben Lindhauer [ thorben.lindhauer ] New: Daniel Kelemen [ daniel.kelemen ]
            DRI New: Daniel Kelemen [ JIRAUSER20104 ]
            Daniel Kelemen made changes -
            Status Original: Open [ 1 ] New: In Progress [ 3 ]

              michael.schoettes Michael Schoettes
              daniel.kelemen Daniel Kelemen
              Daniel Kelemen Daniel Kelemen
              Thorben Lindhauer Thorben Lindhauer
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: