[Bugfix] Race condition in MultiprocExecutor when concurent access to Scheduler (#1448)

Signed-off-by: knlnguyen1802 <knlnguyen1802@gmail.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
This commit is contained in:
knlnguyen1802andHongsheng Liu authored and GitHub committed 2026-02-26 21:03:38 +08:00
1 parent 03c01e0415
commit 5361353be5
4 files changed
+504 -45

No files matched your search

@@ -160,33 +160,43 @@ class MultiprocDiffusionExecutor(DiffusionExecutor):
}
try:
# Broadcast RPC request to all workers via unified message queue
self.scheduler.mq.enqueue(rpc_request)
# Acquire lock with timeout awareness so that a stalled add_req
# (holding the lock while blocked on dequeue) does not prevent
# this RPC from honouring its own timeout.
lock_timeout = None if deadline is None else max(0, deadline - time.monotonic())
acquired = self.scheduler._lock.acquire(timeout=lock_timeout if lock_timeout is not None else -1)
if not acquired:
raise TimeoutError(f"RPC call to {method} timed out waiting for scheduler lock.")
try:
# Broadcast RPC request to all workers via unified message queue
self.scheduler.mq.enqueue(rpc_request)
# Determine which workers we expect responses from
num_responses = 1 if unique_reply_rank is not None else self.od_config.num_gpus
# Determine which workers we expect responses from
num_responses = 1 if unique_reply_rank is not None else self.od_config.num_gpus
responses = []
for _ in range(num_responses):
dequeue_timeout = None if deadline is None else (deadline - time.monotonic())
try:
if self.scheduler.result_mq is None:
raise RuntimeError("Result queue not initialized")
responses = []
for _ in range(num_responses):
dequeue_timeout = None if deadline is None else max(0, deadline - time.monotonic())
try:
if self.scheduler.result_mq is None:
raise RuntimeError("Result queue not initialized")
response = self.scheduler.result_mq.dequeue(timeout=dequeue_timeout)
response = self.scheduler.result_mq.dequeue(timeout=dequeue_timeout)
# Check if response indicates an error
if isinstance(response, dict) and response.get("status") == "error":
raise RuntimeError(
f"Worker failed with error '{response.get('error')}', "
"please check the stack trace above for the root cause"
)
# Check if response indicates an error
if isinstance(response, dict) and response.get("status") == "error":
raise RuntimeError(
f"Worker failed with error '{response.get('error')}', "
"please check the stack trace above for the root cause"
)
responses.append(response)
except TimeoutError as e:
raise TimeoutError(f"RPC call to {method} timed out.") from e
responses.append(response)
except TimeoutError as e:
raise TimeoutError(f"RPC call to {method} timed out.") from e
return responses[0] if unique_reply_rank is not None else responses
return responses[0] if unique_reply_rank is not None else responses
finally:
self.scheduler._lock.release()
except Exception as e:
logger.error(f"RPC call failed: {e}")