Mark Payne created NIFI-16308:
---------------------------------

             Summary: StandardConnectorNode can schedule duplicate concurrent 
starts
                 Key: NIFI-16308
                 URL: https://issues.apache.org/jira/browse/NIFI-16308
             Project: Apache NiFi
          Issue Type: Bug
            Reporter: Mark Payne


h2. Description

StandardConnectorNode.start() reads the current Connector state and then 
unconditionally sets it to STARTING. When two callers start the same Connector 
concurrently, both can observe STOPPED and both can schedule startComponent(). 
The second state update is logged as STARTING -> STARTING.

This was observed while validating the Connector mock framework against the 
Kafka-to-S3 Connector. ConnectorTestRunner.applyUpdate() initiated an 
asynchronous stop and returned. An immediate explicit start set the desired 
state to RUNNING. When the stop completed, StandardConnectorNode also initiated 
its automatic restart, allowing both start calls to proceed concurrently.

h2. Reproduction

# Begin an asynchronous Connector stop.
# Request start while the current state is STOPPING, setting the desired state 
to RUNNING.
# Allow stopComponent() to reach STOPPED and invoke its automatic restart.
# Arrange for the explicit start and automatic restart to complete validation 
together.
# Observe both callers read STOPPED, followed by STOPPED -> STARTING and 
STARTING -> STARTING transitions.

h2. Impact

Both calls invoke Connector.start() and attempt to start the same managed 
processors and controller services. The first path can reach RUNNING while the 
duplicate path is refused because components are already STARTING. Completion 
futures created for the duplicate processor starts may never complete, which 
can strand the associated Connector start Future even though the Connector is 
running. Callers that wait on that Future can hang or time out, and Connector 
lifecycle callbacks can execute concurrently.

h2. Proposed Correction

Use an atomic compare-and-set loop when transitioning an eligible state to 
STARTING. A caller that loses the transition should re-read the state and 
register its Future as pending instead of scheduling another component start. 
Pending-start registration must also be atomic with the transition to RUNNING 
so a Future cannot be registered immediately after pending futures have already 
been completed.

Add a deterministic concurrency regression that releases two start requests 
after both have entered validation, then verifies Connector.start() is invoked 
once and both returned Futures complete.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to