aglinxinyuan opened a new issue, #6923:
URL: https://github.com/apache/texera/issues/6923

   ### What happened?
   
   Region-termination retry attempts run on a `JavaTimer` thread and mutate 
coordinator RPC state that is not thread-safe, concurrently with the 
coordinator's actor thread. This is a latent data race — no observed corruption 
yet, but nothing prevents it.
   
   Thread switch: attempt 1 of `terminateWorkersWithRetry` runs on the 
coordinator actor thread (inside the `portCompleted` handler continuation), but 
every retry runs on the timer thread:
   
   ```scala
   // RegionExecutionManager.scala:129
   private val killRetryTimer: Timer = new JavaTimer(true)
   // :255-257
   Future.sleep(killRetryDelay)(killRetryTimer)
     .flatMap(_ => terminateWorkersWithRetry(regionExecution, attempt + 1))   
// <- runs on the JavaTimer thread
   ```
   
   `terminateWorkers` then calls 
`asyncRPCClient.workerInterface.endWorker(...)`, which touches unsynchronized 
shared state:
   
   | state | declaration | mutated by |
   |---|---|---|
   | `promiseID` | plain `var` (`AsyncRPCClient.scala:137`) | `createPromise` 
(:145-150) on the timer thread; same path on the actor thread for every other 
RPC |
   | `unfulfilledPromises` | unsynchronized `mutable.HashMap` 
(`AsyncRPCClient.scala:136`) | `createPromise` on the timer thread; 
`fulfillPromise` on the actor thread for every inbound reply |
   | `idToSequenceNums` | unsynchronized `mutable.HashMap` 
(`NetworkOutputGateway.scala:47`) | `getSequenceNumber` uses `getOrElseUpdate` 
(:93-95) with no lock (note `removeControlChannel` :97-101 IS `synchronized`, 
so the intent to synchronize exists but is inconsistent) |
   
   Consequences range from lost/duplicated promise ids (an RPC whose reply can 
never be matched → termination hang) to `HashMap` structural corruption under 
concurrent resize.
   
   Also on this path: `gracefulStop(...)` future callbacks update 
`WorkerExecution` state from Pekko dispatcher threads 
(`RegionExecutionManager.scala:214-219`), so worker-state writes are concurrent 
with coordinator-thread reads (this interacts with the stats-aggregation issue, 
filed separately).
   
   Fix directions: hop back to the coordinator's serialized execution context 
for the retry continuation (instead of running `terminateWorkers` directly on 
the timer thread), or make the touched structures thread-safe and document the 
invariant.
   
   ### How to reproduce?
   
   Code inspection; the race window is every retried termination attempt (any 
teardown that fails attempt 1) racing against any concurrent coordinator RPC 
(e.g. periodic stats queries).
   
   ### Version/Branch
   
   main (observed at 429be110a7; discovered during the investigation for #6916).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to