From eaacf10f7141caaff9f34221bee3a8e5ede636cb Mon Sep 17 00:00:00 2001 From: comex Date: Tue, 10 Dec 2013 00:27:20 -0500 Subject: [PATCH] Fix an idiotic race condition when starting games in multiple Dolphin instances at the same time on Unix. MemArena mmaps the emulated memory from a file in order to get the same mapping at multiple addresses. A file which, formerly, was located at a static filename: it was unlinked after creation, but the open did not use O_EXCL, so if two instances started up on the same system at just the right time, they would get the same memory. Naturally, this caused extremely mysterious crashes, but only in Netplay, where the game is automatically started when the client receives a broadcast from the server, so races are actually quite likely. And switch to shm_open, because it fits the bill better and avoids any issues with using /tmp. --- Source/Core/Common/Src/MemArena.cpp | 25 +++++++++++++++---------- Source/Core/DolphinWX/CMakeLists.txt | 4 ++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Source/Core/Common/Src/MemArena.cpp b/Source/Core/Common/Src/MemArena.cpp index 6b69b63860..e7f3911e91 100644 --- a/Source/Core/Common/Src/MemArena.cpp +++ b/Source/Core/Common/Src/MemArena.cpp @@ -21,11 +21,6 @@ #endif #endif -#if defined(__APPLE__) -static const char* ram_temp_file = "/tmp/gc_mem.tmp"; -#elif !defined(_WIN32) // non OSX unixes -static const char* ram_temp_file = "/dev/shm/gc_mem.tmp"; -#endif #ifdef ANDROID #define ASHMEM_DEVICE "/dev/ashmem" @@ -62,12 +57,22 @@ void MemArena::GrabLowMemSpace(size_t size) return; } #else - mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - fd = open(ram_temp_file, O_RDWR | O_CREAT, mode); - unlink(ram_temp_file); + char fn[64]; + for (int i = 0; i < 10000; i++) + { + sprintf(fn, "dolphinmem.%d", i); + fd = shm_open(fn, O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd != -1) + break; + if (errno != EEXIST) + { + ERROR_LOG(MEMMAP, "shm_open failed: %s", strerror(errno)); + return; + } + } + shm_unlink(fn); if (ftruncate(fd, size) < 0) ERROR_LOG(MEMMAP, "Failed to allocate low memory space"); - return; #endif } @@ -96,7 +101,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base) if (retval == MAP_FAILED) { - NOTICE_LOG(MEMMAP, "mmap on %s failed", ram_temp_file); + NOTICE_LOG(MEMMAP, "mmap failed"); return nullptr; } else diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt index a35f1ba1ce..68728dc6fe 100644 --- a/Source/Core/DolphinWX/CMakeLists.txt +++ b/Source/Core/DolphinWX/CMakeLists.txt @@ -13,6 +13,10 @@ set(LIBS core sfml-network ${GTK2_LIBRARIES}) +if((NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) + set(LIBS ${LIBS} rt) +endif() + if(NOT ANDROID) if(USE_X11) set(LIBS ${LIBS} ${X11_LIBRARIES}