From 839c511af40aa60277563a6b54a27e122584c97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 20 Aug 2024 19:53:08 +0200 Subject: [PATCH] Make macOS semaphore names more unique, improve assertion On macOS, semaphore names are global and processes can open semaphores of other processes by using their name. It was possible that multiple client/server processes randomly tried to create semaphores with the same memory address, which would cause them to have the same name. In that case, `sem_open` would fail because `O_EXCL` prevents creating semaphores if the name is already used. This is made more unlikely by also including the PID in the semaphore name. Additionally, the semaphore name is prefixed with `/` to more closely follow the construction rules for semaphore names. In particular, the behavior is implementation-defined if the name is not prefixed with a slash. See https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_open.html Closes #8773. More details are added to the assertion error message in case this does not end up fixing the issue. --- src/base/system.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/base/system.cpp b/src/base/system.cpp index 2859ab07f..b244163f9 100644 --- a/src/base/system.cpp +++ b/src/base/system.cpp @@ -867,10 +867,15 @@ void sphore_destroy(SEMAPHORE *sem) #elif defined(CONF_PLATFORM_MACOS) void sphore_init(SEMAPHORE *sem) { - char aBuf[32]; - str_format(aBuf, sizeof(aBuf), "%p", (void *)sem); + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "/%d.%p", pid(), (void *)sem); *sem = sem_open(aBuf, O_CREAT | O_EXCL, S_IRWXU | S_IRWXG, 0); - dbg_assert(*sem != SEM_FAILED, "sem_open failure"); + if(*sem == SEM_FAILED) + { + char aError[128]; + str_format(aError, sizeof(aError), "sem_open failure, errno=%d, name='%s'", errno, aBuf); + dbg_assert(false, aError); + } } void sphore_wait(SEMAPHORE *sem) { @@ -888,8 +893,8 @@ void sphore_signal(SEMAPHORE *sem) void sphore_destroy(SEMAPHORE *sem) { dbg_assert(sem_close(*sem) == 0, "sem_close failure"); - char aBuf[32]; - str_format(aBuf, sizeof(aBuf), "%p", (void *)sem); + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "/%d.%p", pid(), (void *)sem); dbg_assert(sem_unlink(aBuf) == 0, "sem_unlink failure"); } #elif defined(CONF_FAMILY_UNIX)