Skip to content

Commit 868c9e5

Browse files
committed
fix: correct lock ordering in processMeshRequest to prevent deadlock
The previous lock ordering in processMeshRequest was: epochLock -> sizeLock -> arenaLock This conflicted with meshAllSizeClassesLocked (called via mallctl mesh.compact with AllLocksGuard) which uses: sizeLocks[0..N-1] -> arenaLock -> epochLock This inconsistent ordering could cause deadlock: - Thread A (mallctl): holds miniheapLocks, waits for epochLock - Thread B (processMeshRequest): holds epochLock, waits for miniheapLock Fix by reordering processMeshRequest to match the established order: sizeLock -> arenaLock -> epochLock Also moves drainPendingPartialLocked inside the epoch-locked section to match the pattern in meshAllSizeClassesLocked.
1 parent 9b13777 commit 868c9e5

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

src/global_heap_impl.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,9 @@ void GlobalHeap<PageSize>::processMeshRequest(size_t sizeClass) {
331331
bool aboveThreshold = false;
332332

333333
{
334-
lock_guard<EpochLock> epochLock(_meshEpoch);
334+
// Lock ordering: size-class lock -> arena lock -> epoch lock
335+
// This matches meshAllSizeClassesLocked (called via AllLocksGuard in mallctl)
335336
lock_guard<mutex> sizeLock(_miniheapLocks[sizeClass]);
336-
drainPendingPartialLocked(sizeClass);
337-
338337
lock_guard<mutex> arenaLock(_arenaLock);
339338

340339
// if we have freed but not reset meshed mappings, this will reset
@@ -345,6 +344,10 @@ void GlobalHeap<PageSize>::processMeshRequest(size_t sizeClass) {
345344
if (Super::aboveMeshThreshold()) {
346345
aboveThreshold = true;
347346
} else {
347+
// Acquire epoch lock last to match lock ordering in meshAllSizeClassesLocked
348+
lock_guard<EpochLock> epochLock(_meshEpoch);
349+
350+
drainPendingPartialLocked(sizeClass);
348351
flushBinLocked(sizeClass);
349352
meshCount = meshSizeClassLocked(sizeClass, scratch.mergeSets, scratch.left, scratch.right);
350353
madvise(&scratch.left, sizeof(scratch.left), MADV_DONTNEED);

0 commit comments

Comments
 (0)