pytorch - 💡(How to fix) Fix Race condition updating pgStatus_ in ProcessGroupGloo::runLoop

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

We're seeing training runs fail due to abort signals with error message malloc(): unaligned tcache chunk detected. Irritatingly, the failure is very reliable but often takes a long time to trigger. I haven't managed to come up with a small example reproducing the problem but I do believe I've found the root cause: the updates to ProcessGroupGloo::pgStatus_ below should happen after lock.lock(); on line 721. https://github.com/pytorch/pytorch/blob/44a01f77e0461b27be1f10c43e5574f74659cbf1/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp#L711-L721

Root Cause

We're seeing training runs fail due to abort signals with error message malloc(): unaligned tcache chunk detected. Irritatingly, the failure is very reliable but often takes a long time to trigger. I haven't managed to come up with a small example reproducing the problem but I do believe I've found the root cause: the updates to ProcessGroupGloo::pgStatus_ below should happen after lock.lock(); on line 721. https://github.com/pytorch/pytorch/blob/44a01f77e0461b27be1f10c43e5574f74659cbf1/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp#L711-L721

Fix Action

Fix / Workaround

CPU: Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 39 bits physical, 48 bits virtual Byte Order: Little Endian CPU(s): 16 On-line CPU(s) list: 0-15 Vendor ID: GenuineIntel Model name: 11th Gen Intel(R) Core(TM) i9-11900 @ 2.50GHz CPU family: 6 Model: 167 Thread(s) per core: 2 Core(s) per socket: 8 Socket(s): 1 Stepping: 1 CPU(s) scaling MHz: 30% CPU max MHz: 5200.0000 CPU min MHz: 800.0000 BogoMIPS: 4992.00 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx avx512f avx512dq rdseed adx smap avx512ifma clflushopt intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid fsrm md_clear flush_l1d arch_capabilities Virtualization: VT-x L1d cache: 384 KiB (8 instances) L1i cache: 256 KiB (8 instances) L2 cache: 4 MiB (8 instances) L3 cache: 16 MiB (1 instance) NUMA node(s): 1 NUMA node0 CPU(s): 0-15 Vulnerability Gather data sampling: Mitigation; Microcode Vulnerability Indirect target selection: Mitigation; Aligned branch/return thunks Vulnerability Itlb multihit: Not affected Vulnerability L1tf: Not affected Vulnerability Mds: Not affected Vulnerability Meltdown: Not affected Vulnerability Mmio stale data: Mitigation; Clear CPU buffers; SMT vulnerable Vulnerability Reg file data sampling: Not affected Vulnerability Retbleed: Mitigation; Enhanced IBRS Vulnerability Spec rstack overflow: Not affected Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization Vulnerability Spectre v2: Mitigation; Enhanced / Automatic IBRS; IBPB conditional; PBRSB-eIBRS SW sequence; BHI SW loop, KVM SW loop Vulnerability Srbds: Not affected Vulnerability Tsa: Not affected Vulnerability Tsx async abort: Not affected Vulnerability Vmscape: Not affected

Code Example

diff --git a/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp b/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp
index c81516b10ba..414c303fc08 100644
--- a/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp
+++ b/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp
@@ -709,6 +709,7 @@ void ProcessGroupGloo::runLoop(int workerIndex) {
     workConsumeCV_.notify_one();
 
     AsyncWork::execute(work);
+    lock.lock();
     // TODO: Need to find a way to calculate the difference of duration of two
     // c10d::Event
     pgStatus_->lastCompletedSeq = static_cast<int64_t>(work->seq_);
@@ -718,7 +719,6 @@ void ProcessGroupGloo::runLoop(int workerIndex) {
     pgStatus_->lastCompletedNumelOut = 0;
     FlightRecorder<c10::Event>::get()->retire_id(
         work->trace_id_, work->trace_reset_epoch_, false);
-    lock.lock();
     workInProgress_[workerIndex].reset();
   }
 }
RAW_BUFFERClick to expand / collapse

🐛 Describe the bug

We're seeing training runs fail due to abort signals with error message malloc(): unaligned tcache chunk detected. Irritatingly, the failure is very reliable but often takes a long time to trigger. I haven't managed to come up with a small example reproducing the problem but I do believe I've found the root cause: the updates to ProcessGroupGloo::pgStatus_ below should happen after lock.lock(); on line 721. https://github.com/pytorch/pytorch/blob/44a01f77e0461b27be1f10c43e5574f74659cbf1/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp#L711-L721

Again, I don't have a small reproduction but it looks like a clear race condition: multiple threads are running ProcessGroupGloo::runLoop so updates to shared state need to be protected by the mutex. Also, I reproduced the problem using PyTorch built from source, and was then unable to reproduce it after moving lock.lock() before pgStatus_ updates and rebuilding. I also managed to catch the problem live in a debugger and indeed the corruption malloc was complaining about was consistent with racy pgStatus_->lastCompletedWorkName = opTypeToString(work->opType_) updates.

Here is the diff that fixed the problem for me:

diff --git a/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp b/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp
index c81516b10ba..414c303fc08 100644
--- a/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp
+++ b/torch/csrc/distributed/c10d/ProcessGroupGloo.cpp
@@ -709,6 +709,7 @@ void ProcessGroupGloo::runLoop(int workerIndex) {
     workConsumeCV_.notify_one();
 
     AsyncWork::execute(work);
+    lock.lock();
     // TODO: Need to find a way to calculate the difference of duration of two
     // c10d::Event
     pgStatus_->lastCompletedSeq = static_cast<int64_t>(work->seq_);
@@ -718,7 +719,6 @@ void ProcessGroupGloo::runLoop(int workerIndex) {
     pgStatus_->lastCompletedNumelOut = 0;
     FlightRecorder<c10::Event>::get()->retire_id(
         work->trace_id_, work->trace_reset_epoch_, false);
-    lock.lock();
     workInProgress_[workerIndex].reset();
   }
 }

Happy to turn that into a PR if necessary or convenient

Versions

Collecting environment information... PyTorch version: 2.10.0+cu126 Is debug build: False CUDA used to build PyTorch: 12.6 ROCM used to build PyTorch: N/A

OS: Debian GNU/Linux 13 (trixie) (x86_64) GCC version: (Debian 14.2.0-19) 14.2.0 Clang version: Could not collect CMake version: Could not collect Libc version: glibc-2.41

Python version: 3.13.5 (main, Jun 25 2025, 18:55:22) [GCC 14.2.0] (64-bit runtime) Python platform: Linux-5.15.0-164-generic-x86_64-with-glibc2.41 Is CUDA available: True CUDA runtime version: Could not collect CUDA_MODULE_LOADING set to: GPU models and configuration: GPU 0: NVIDIA A40 Nvidia driver version: 535.274.02 cuDNN version: Could not collect Is XPU available: False HIP runtime version: N/A MIOpen runtime version: N/A Is XNNPACK available: True Caching allocator config: N/A

CPU: Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 39 bits physical, 48 bits virtual Byte Order: Little Endian CPU(s): 16 On-line CPU(s) list: 0-15 Vendor ID: GenuineIntel Model name: 11th Gen Intel(R) Core(TM) i9-11900 @ 2.50GHz CPU family: 6 Model: 167 Thread(s) per core: 2 Core(s) per socket: 8 Socket(s): 1 Stepping: 1 CPU(s) scaling MHz: 30% CPU max MHz: 5200.0000 CPU min MHz: 800.0000 BogoMIPS: 4992.00 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx avx512f avx512dq rdseed adx smap avx512ifma clflushopt intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid fsrm md_clear flush_l1d arch_capabilities Virtualization: VT-x L1d cache: 384 KiB (8 instances) L1i cache: 256 KiB (8 instances) L2 cache: 4 MiB (8 instances) L3 cache: 16 MiB (1 instance) NUMA node(s): 1 NUMA node0 CPU(s): 0-15 Vulnerability Gather data sampling: Mitigation; Microcode Vulnerability Indirect target selection: Mitigation; Aligned branch/return thunks Vulnerability Itlb multihit: Not affected Vulnerability L1tf: Not affected Vulnerability Mds: Not affected Vulnerability Meltdown: Not affected Vulnerability Mmio stale data: Mitigation; Clear CPU buffers; SMT vulnerable Vulnerability Reg file data sampling: Not affected Vulnerability Retbleed: Mitigation; Enhanced IBRS Vulnerability Spec rstack overflow: Not affected Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization Vulnerability Spectre v2: Mitigation; Enhanced / Automatic IBRS; IBPB conditional; PBRSB-eIBRS SW sequence; BHI SW loop, KVM SW loop Vulnerability Srbds: Not affected Vulnerability Tsa: Not affected Vulnerability Tsx async abort: Not affected Vulnerability Vmscape: Not affected

Versions of relevant libraries: [pip3] Could not collect [conda] Could not collect

cc @awgu @wanchaol @fegin @fduwjj @wz337 @wconstab @d4l3k @pragupta @msaroufim @dcci @aditvenk @xmfan

extent analysis

TL;DR

The issue can be fixed by moving the lock.lock() call to before the updates to pgStatus_ in the ProcessGroupGloo::runLoop function to prevent a race condition.

Guidance

  • Verify that the issue is indeed caused by a race condition by checking the stacktrace and the code changes that fixed the problem for the reporter.
  • Apply the provided diff to the ProcessGroupGloo::runLoop function to move the lock.lock() call before the updates to pgStatus_.
  • Rebuild PyTorch from source with the applied changes to test if the issue is resolved.
  • Test the fix in a multi-threaded environment to ensure that the race condition is properly mitigated.

Example

The provided diff shows the necessary code changes:

void ProcessGroupGloo::runLoop(int workerIndex) {
    ...
    AsyncWork::execute(work);
    lock.lock(); // Move lock.lock() before updates to pgStatus_
    pgStatus_->lastCompletedSeq = static_cast<int64_t>(work->seq_);
    ...
}

Notes

The fix assumes that the issue is indeed caused by a race condition in the ProcessGroupGloo::runLoop function. If the issue persists after applying the fix, further debugging and testing may be necessary.

Recommendation

Apply the workaround by moving the lock.lock() call before the updates to pgStatus_ in the ProcessGroupGloo::runLoop function, as this has been reported to fix the issue for the reporter.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

pytorch - 💡(How to fix) Fix Race condition updating pgStatus_ in ProcessGroupGloo::runLoop