From 6b43daccf0d79a0f0f2e1a3c3f9c0bfd66daabaa Mon Sep 17 00:00:00 2001 From: Nick Rogers <1903140+rogersnm@users.noreply.github.com> Date: Wed, 30 Sep 2026 14:43:05 +0100 Subject: [PATCH] FEXCore/Allocator: Don't hang when /proc/self/maps can't be opened StealMemoryRegion guards the open() with LogMan::Throw::AFmt, which compiles out in release builds. With no procfs mounted the fd is -1 and CollectMemoryGaps then loops on read(-1) forever at 100% CPU. This is hit whenever FEX is the x86_64 binfmt handler and something runs an x86 binary in a root without /proc. BuildKit does exactly that: its emulator probe execs a static x86_64 binary in an empty chroot, so every BuildKit start on an Arm host with FEX registered hangs. Reserve nothing instead: StealMemoryRegion returns no regions and Setup48BitAllocatorIfExists skips the 48-bit allocator. The guest then runs without the upper VA hidden, which only matters in environments that previously never got past startup. --- FEXCore/Source/Utils/Allocator.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/FEXCore/Source/Utils/Allocator.cpp b/FEXCore/Source/Utils/Allocator.cpp index 3a779abaf..18495ce6e 100644 --- a/FEXCore/Source/Utils/Allocator.cpp +++ b/FEXCore/Source/Utils/Allocator.cpp @@ -218,7 +218,12 @@ fextl::vector StealMemoryRegion(uintptr_t Begin, uintptr_t End) { const uintptr_t StackLocation_u64 = reinterpret_cast(alloca(0)); const int MapsFD = open("/proc/self/maps", O_RDONLY); - LogMan::Throw::AFmt(MapsFD != -1, "Failed to open /proc/self/maps"); + if (MapsFD == -1) { + // No procfs, as in BuildKit's emulator probe (an empty chroot). The assert + // above it compiles out in release, and CollectMemoryGaps then spins on + // read(-1) forever; reserve nothing instead. + return {}; + } auto Regions = CollectMemoryGaps(Begin, End, MapsFD); close(MapsFD); @@ -282,6 +287,9 @@ fextl::vector Setup48BitAllocatorIfExists(size_t PageSize) { uintptr_t Begin48BitVA = 0x0'8000'0000'0000ULL; uintptr_t End48BitVA = 0x1'0000'0000'0000ULL; auto Regions = StealMemoryRegion(Begin48BitVA, End48BitVA); + if (Regions.empty()) { + return {}; + } Alloc64 = Alloc::OSAllocator::Create64BitAllocatorWithRegions(Regions); AssignHookOverrides(PageSize);