From e9ed44438737a4c41180e51ba36bc921992ad05b Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Wed, 6 Jan 2016 11:56:57 +0100 Subject: [PATCH] Implement singleton locking for POSIX. --- src/platform/posix.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/platform/posix.c b/src/platform/posix.c index 4ce5116756..a6c091590c 100644 --- a/src/platform/posix.c +++ b/src/platform/posix.c @@ -43,9 +43,10 @@ #include #include #include +#include // The name of the mutex used to prevent multiple instances of the game from running -#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX" +#define SINGLE_INSTANCE_MUTEX_NAME "openrct2.lock" #define FILE_BUFFER_SIZE 4096 @@ -226,7 +227,32 @@ bool platform_directory_delete(const utf8 *path) bool platform_lock_single_instance() { - STUB(); + char pidFilePath[MAX_PATH]; + char separator = platform_get_path_separator(); + + strncpy(pidFilePath, _userDataDirectoryPath, MAX_PATH); + strncat(pidFilePath, &separator, 1); + strncat(pidFilePath, SINGLE_INSTANCE_MUTEX_NAME, + MAX_PATH - strnlen(pidFilePath, MAX_PATH) - 1); + + // We will never close this file manually. The operating system will + // take care of that, because flock keeps the lock as long as the + // file is open and closes it automatically on file close. + // This is intentional. + int pidFile = open(pidFilePath, O_CREAT | O_RDWR, 0666); + + if (pidFile == -1) { + log_warning("Cannot open lock file for writing."); + return false; + } + if (flock(pidFile, LOCK_EX | LOCK_NB) == -1) { + if (errno == EWOULDBLOCK) { + log_warning("Another OpenRCT2 session has been found running."); + return false; + } + log_error("flock returned an uncatched errno: %d", errno); + return false; + } return true; }