Repository navigation
[bug] temporary_distributed_context has a singleton TCP rendezvous race #5967
Description
Problem
temporary_distributed_context() currently discovers a TCP rendezvous port by binding localhost:0, closes that socket, and then asks torch.distributed.init_process_group() to bind the same address:
Megatron-Bridge/src/megatron/bridge/training/model_load_save.py
Lines 131 to 140 in 8a83605
| if "MASTER_ADDR" in os.environ and "MASTER_PORT" in os.environ: | |
| init_method = None | |
| else: | |
| # Find an available port dynamically | |
| with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | |
| s.bind(("localhost", 0)) | |
| addr, port = s.getsockname() | |
| init_method = f"tcp://{addr}:{port}" | |
| dist.init_process_group(backend=backend, init_method=init_method, world_size=1, rank=0) |
That creates a time-of-check/time-of-use race: another process can claim the port before Gloo binds it, causing EADDRINUSE / address already in use.
Standalone AutoBridge.import_ckpt() and AutoBridge.export_ckpt() use this temporary context when the caller has no initialized process group:
Megatron-Bridge/src/megatron/bridge/models/conversion/auto_bridge.py
Lines 1494 to 1497 in 8a83605
from megatron.bridge.training.model_load_save import temporary_distributed_context model_context = nullcontext() if dist.is_initialized() else temporary_distributed_context(backend="gloo") with model_context: Megatron-Bridge/src/megatron/bridge/models/conversion/auto_bridge.py
Lines 1577 to 1583 in 8a83605
from megatron.bridge.training.model_load_save import temporary_distributed_context except ImportError: raise ImportError("megatron.bridge.training is not available.") # Export ckpt performs on CPU model_context = nullcontext() if dist.is_initialized() else temporary_distributed_context(backend="gloo") with model_context:
PR #5696 correctly preserves a caller-owned process group, but standalone callers still enter this path.
Minimal repro
# Run on Linux with Megatron-Bridge and the Gloo backend available.
# This is a race, so increase the count/parallelism if needed.
unset MASTER_ADDR MASTER_PORT
seq 1 200 | xargs -n1 -P32 sh -c '
python - <<'"'"'PY'"'"'
from megatron.bridge.training.model_load_save import temporary_distributed_context
with temporary_distributed_context(backend="gloo"):
pass
PY
'The same class of race produced an EADDRINUSE failure in the project's public CI:
https://github.com/NVIDIA-NeMo/Megatron-Bridge/actions/runs/31846107309/job/94940794151
Expected behavior
A world-size-one temporary process group should initialize and clean up without racing on a host TCP port or depending on inherited rendezvous environment variables.
Affected area
area:ckpt
Regression?
Not sure. The current helper has used this rendezvous pattern since it was introduced.
Environment
- Current
main:8a8360510adcd43ad1154d54bb25928468bc7288 - Latest checked release:
v0.6.0(51885cf132b2814188b6855c25a8588254274c2a) - Backend: Gloo
- World size: 1
- Reproduced through standalone checkpoint conversion/export; the race itself is GPU-independent
Suggested direction
Because this context is explicitly single-process, an in-process torch.distributed.HashStore() can be passed through store= to init_process_group(), avoiding TCP rendezvous entirely.
Closed PR #5595 proposed that implementation and focused Gloo/NCCL coverage:
I could not find a merged replacement for #5595, and current main still contains the TCP bind-close-rebind implementation. Was #5595 intentionally superseded, or would a new focused PR for this change be welcome?
Activity
fix: use in-process HashStore for temporary_distributed_context rende…
jasonliu-shop commentedon Sep 20, 2026
Thanks @cuichenx AND @ManoharPaturi !