Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
comex committed Dec 10, 2013
1 parent 2d8515c commit eaacf10
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 10 deletions.
25 changes: 15 additions & 10 deletions Source/Core/Common/Src/MemArena.cpp
Expand Up @@ -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"

Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions Source/Core/DolphinWX/CMakeLists.txt
Expand Up @@ -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}
Expand Down

0 comments on commit eaacf10

Please sign in to comment.