Common/MemArena: make shared memory name unique per DLL instance

When multiple copies of the same DLL are loaded into the same process
(e.g. for libretro multi-instance support), all copies share the same
PID. Using only the PID as the name suffix caused CreateFileMapping to
return the existing named kernel object instead of creating a new one,
so both instances silently mapped the same 4GB+ GameCube/Wii RAM region
and instantly corrupted each other.

Fix this by also embedding the address of a static-local variable in the
name. Because each DLL copy is mapped at a different base address in the
process, s_dll_id lives at a unique virtual address in every copy, so
its value acts as a stable, zero-cost, per-instance discriminator.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Ryan McClelland 2026-03-11 11:25:59 -07:00
parent 30a735aa6f
commit 7be243a8b4

View File

@ -120,7 +120,14 @@ static DWORD GetLowDWORD(u64 value)
void MemArena::GrabSHMSegment(size_t size, std::string_view base_name)
{
const std::string name = fmt::format("{}.{}", base_name, GetCurrentProcessId());
// Include the address of a static local as a per-DLL-instance unique ID.
// When multiple copies of this DLL are loaded in the same process they share
// the same PID, so we need an additional discriminator. Each copy is mapped
// at a different base address, so s_dll_id's address (and thus its value) is
// unique per loaded instance.
static const uintptr_t s_dll_id = reinterpret_cast<uintptr_t>(&s_dll_id);
const std::string name =
fmt::format("{}.{}.{:x}", base_name, GetCurrentProcessId(), s_dll_id);
m_memory_handle =
CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, GetHighDWORD(size),
GetLowDWORD(size), UTF8ToTStr(name).c_str());