[scudo] Improve the message of region exhaustion (#68444)

In this CL, we move the printing of allocator stats from primary.h to
combined.h. This will also dump the secondary stats and reduce the log
spam when an OOM happens

Also change the symbol `F` to `E` to indicate region pages exhausted. It
means the region can't map more pages for blocks but it may still have
free blocks to allocate. `F` may hint the failure of fatel error in the
region. Also update the related comments.
This commit is contained in:
ChiaHungDuan 2023-10-06 14:31:33 -07:00 committed by GitHub
parent 0637440002
commit b53ff43d36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 10 additions and 16 deletions

View File

@ -367,10 +367,9 @@ public:
auto *TSD = TSDRegistry.getTSDAndLock(&UnlockRequired);
TSD->assertLocked(/*BypassCheck=*/!UnlockRequired);
Block = TSD->getCache().allocate(ClassId);
// If the allocation failed, the most likely reason with a 32-bit primary
// is the region being full. In that event, retry in each successively
// larger class until it fits. If it fails to fit in the largest class,
// fallback to the Secondary.
// If the allocation failed, retry in each successively larger class until
// it fits. If it fails to fit in the largest class, fallback to the
// Secondary.
if (UNLIKELY(!Block)) {
while (ClassId < SizeClassMap::LargestClassId && !Block)
Block = TSD->getCache().allocate(++ClassId);
@ -388,6 +387,7 @@ public:
if (UNLIKELY(!Block)) {
if (Options.get(OptionBit::MayReturnNull))
return nullptr;
printStats();
reportOutOfMemory(NeededSize);
}

View File

@ -214,7 +214,7 @@ public:
return B;
}
bool PrintStats = false;
bool ReportRegionExhausted = false;
TransferBatch *B = nullptr;
while (true) {
@ -235,19 +235,13 @@ public:
const bool RegionIsExhausted = Region->Exhausted;
if (!RegionIsExhausted)
B = populateFreeListAndPopBatch(C, ClassId, Region);
PrintStats = !RegionIsExhausted && Region->Exhausted;
ReportRegionExhausted = !RegionIsExhausted && Region->Exhausted;
break;
}
// Note that `getStats()` requires locking each region so we can't call it
// while locking the Region->Mutex in the above.
if (UNLIKELY(PrintStats)) {
ScopedString Str;
getStats(&Str);
Str.append(
"Scudo OOM: The process has exhausted %zuM for size class %zu.\n",
RegionSize >> 20, getSizeByClassId(ClassId));
Str.output();
if (UNLIKELY(ReportRegionExhausted)) {
Printf("Can't populate more pages for size class %zu.\n",
getSizeByClassId(ClassId));
// Theoretically, BatchClass shouldn't be used up. Abort immediately when
// it happens.
@ -978,7 +972,7 @@ private:
"%s %02zu (%6zu): mapped: %6zuK popped: %7zu pushed: %7zu "
"inuse: %6zu total: %6zu releases: %6zu last "
"released: %6zuK latest pushed bytes: %6zuK region: 0x%zx (0x%zx)\n",
Region->Exhausted ? "F" : " ", ClassId, getSizeByClassId(ClassId),
Region->Exhausted ? "E" : " ", ClassId, getSizeByClassId(ClassId),
Region->MemMapInfo.MappedUser >> 10, Region->FreeListInfo.PoppedBlocks,
Region->FreeListInfo.PushedBlocks, InUseBlocks, TotalChunks,
Region->ReleaseInfo.RangesReleased,