Skip to content

[bug] temporary_distributed_context has a singleton TCP rendezvous race #5967

Closed

Description

@jasonliu-shop

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:

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:

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:

#5595

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

  1. added
    area:ckptCheckpoint conversion, loading, export, and save paths
    bugSomething isn't working
    needs-triageNew item needs classification and ownership
    on Sep 4, 2026
  2. added a commit that references this issue on Sep 7, 2026
    4d482a6
  3. jasonliu-shop commented on Sep 20, 2026

    @jasonliu-shop
    Author
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:ckptCheckpoint conversion, loading, export, and save pathsbugSomething isn't workingcommunity-requestneeds-triageNew item needs classification and ownership

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions