From e24d97bbe433ac9a54bf1ffcb205d3f3eaeee830 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 21 May 2024 22:38:33 +1000 Subject: [PATCH] Common: Don't use MAP_FIXED on Linux MAP_FIXED will clobber any existing memory mapping, and is not safe to use in a multi-threaded environment. Whether we like it or not, we are a multi-threaded environment, because Qt initializes before we get to main(), so it's already too late to safely use MAP_FIXED by the time we get there. Use MAP_FIXED_NOREPLACE instead. This is how MAP_FIXED should have behaved from the beginning. Obviously this means you'll need Linux 4.17+ and a semi-recent libc to use PCSX2 now. But if you're running a 6 year old unsupported kernel, you have bigger problems. Fixes "random" startup crashes. --- common/Linux/LnxHostSys.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/Linux/LnxHostSys.cpp b/common/Linux/LnxHostSys.cpp index 397cfa24e0..81aa1eed4a 100644 --- a/common/Linux/LnxHostSys.cpp +++ b/common/Linux/LnxHostSys.cpp @@ -316,7 +316,7 @@ void* HostSys::MapSharedMemory(void* handle, size_t offset, void* baseaddr, size { const uint lnxmode = LinuxProt(mode); - const int flags = (baseaddr != nullptr) ? (MAP_SHARED | MAP_FIXED) : MAP_SHARED; + const int flags = (baseaddr != nullptr) ? (MAP_SHARED | MAP_FIXED_NOREPLACE) : MAP_SHARED; void* ptr = mmap(baseaddr, size, lnxmode, flags, static_cast(reinterpret_cast(handle)), static_cast(offset)); if (ptr == MAP_FAILED) return nullptr; @@ -326,7 +326,7 @@ void* HostSys::MapSharedMemory(void* handle, size_t offset, void* baseaddr, size void HostSys::UnmapSharedMemory(void* baseaddr, size_t size) { - if (mmap(baseaddr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0) == MAP_FAILED) + if (munmap(baseaddr, size) != 0) pxFailRel("Failed to unmap shared memory"); } @@ -370,6 +370,7 @@ u8* SharedMemoryMappingArea::Map(void* file_handle, size_t file_offset, void* ma { pxAssert(static_cast(map_base) >= m_base_ptr && static_cast(map_base) < (m_base_ptr + m_size)); + // MAP_FIXED is okay here, since we've reserved the entire region, and *want* to overwrite the mapping. const uint lnxmode = LinuxProt(mode); void* const ptr = mmap(map_base, map_size, lnxmode, MAP_SHARED | MAP_FIXED, static_cast(reinterpret_cast(file_handle)), static_cast(file_offset));