From 2a4c9f74586535514a8154b367647756f56ed0eb Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 15 Jun 2020 06:50:33 +0200 Subject: [PATCH] Fixup macos semaphore usage We now store the real bootstrap name in shared memory, and use that name to get the semaphore. This avoid clashes when re-running jack clients, or jack itself. --- macosx/JackMachSemaphore.h | 7 ++- macosx/JackMachSemaphore.mm | 147 ++++++++++++++++++++++++++++++++------------ 2 files changed, 114 insertions(+), 40 deletions(-) diff --git a/macosx/JackMachSemaphore.h b/macosx/JackMachSemaphore.h index d3e5fffa..10406847 100644 --- a/macosx/JackMachSemaphore.h +++ b/macosx/JackMachSemaphore.h @@ -41,13 +41,18 @@ class SERVER_EXPORT JackMachSemaphore : public detail::JackSynchro semaphore_t fSemaphore; mach_port_t fBootPort; + int fSharedMem; + char* fSharedName; + + bool recursiveBootstrapRegister(int counter); + protected: void BuildName(const char* name, const char* server_name, char* res, int size); public: - JackMachSemaphore():JackSynchro(), fSemaphore(0), fBootPort(0) + JackMachSemaphore():JackSynchro(), fSemaphore(0), fBootPort(0), fSharedMem(0), fSharedName(NULL) {} bool Signal(); diff --git a/macosx/JackMachSemaphore.mm b/macosx/JackMachSemaphore.mm index 40152175..2aec0108 100644 --- a/macosx/JackMachSemaphore.mm +++ b/macosx/JackMachSemaphore.mm @@ -21,7 +21,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackConstants.h" #include "JackTools.h" #include "JackError.h" +#include #include +#include namespace Jack { @@ -30,7 +32,12 @@ void JackMachSemaphore::BuildName(const char* client_name, const char* server_na { char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; JackTools::RewriteName(client_name, ext_client_name); - snprintf(res, size, "jacksem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); + + // make the name as small as possible, as macos has issues with long semaphore names + if (strcmp(server_name, "default") == 0) + server_name = ""; + + snprintf(res, size, "js%d.%s%s", JackTools::GetUID(), server_name, ext_client_name); } bool JackMachSemaphore::Signal() @@ -102,6 +109,39 @@ bool JackMachSemaphore::TimedWait(long usec) return (res == KERN_SUCCESS); } +bool JackMachSemaphore::recursiveBootstrapRegister(int counter) +{ + if (counter == 99) + return false; + + kern_return_t res; + + if ((res = bootstrap_register(fBootPort, fSharedName, fSemaphore)) != KERN_SUCCESS) { + switch (res) { + case BOOTSTRAP_SUCCESS : + break; + + case BOOTSTRAP_NOT_PRIVILEGED : + case BOOTSTRAP_NAME_IN_USE : + case BOOTSTRAP_UNKNOWN_SERVICE : + case BOOTSTRAP_SERVICE_ACTIVE : + // try again with next suffix + snprintf(fSharedName, sizeof(fName), "%s-%d", fName, ++counter); + return recursiveBootstrapRegister(counter); + break; + + default : + jack_log("bootstrap_register() err = %i:%s", res, bootstrap_strerror(res)); + break; + } + + jack_error("Allocate: can't check in mach semaphore name = %s err = %i:%s", fName, res, bootstrap_strerror(res)); + return false; + } + + return true; +} + // Server side : publish the semaphore in the global namespace bool JackMachSemaphore::Allocate(const char* name, const char* server_name, int value) { @@ -116,52 +156,36 @@ bool JackMachSemaphore::Allocate(const char* name, const char* server_name, int } } - if ((res = semaphore_create(task, &fSemaphore, SYNC_POLICY_FIFO, value)) != KERN_SUCCESS) { - jack_error("Allocate: can create semaphore err = %i:%s", res, mach_error_string(res)); + if ((fSharedMem = shm_open(fName, O_CREAT | O_RDWR, 0777)) < 0) { + jack_error("Allocate: can't check in named futex name = %s err = %s", fName, strerror(errno)); return false; } - if ((res = bootstrap_register(fBootPort, fName, fSemaphore)) != KERN_SUCCESS) { - switch (res) { - case BOOTSTRAP_SUCCESS : - jack_log("bootstrap_register(): bootstrap success"); - /* service not currently registered, "a good thing" (tm) */ - break; + if (ftruncate(fSharedMem, SYNC_MAX_NAME_SIZE+1) != 0) { + jack_error("Allocate: can't set shared memory size in named futex name = %s err = %s", fName, strerror(errno)); + return false; + } - case BOOTSTRAP_NOT_PRIVILEGED : - jack_log("bootstrap_register(): bootstrap not privileged"); - /* might belong to a previously running jack process that crashed, let's try to connect */ - { - semaphore_t sem; - if (semaphore_create(task, &sem, SYNC_POLICY_FIFO, value) == KERN_SUCCESS) - { - const bool ok = (bootstrap_look_up(fBootPort, fName, &sem) == KERN_SUCCESS); - semaphore_destroy(mach_task_self(), sem); - - if (ok) - { - jack_error("bootstrap_register(): forced connection"); - return true; - } - } - } - break; + char* const sharedName = (char*)mmap(NULL, SYNC_MAX_NAME_SIZE+1, PROT_READ|PROT_WRITE, MAP_SHARED, fSharedMem, 0); - case BOOTSTRAP_SERVICE_ACTIVE : - jack_log("bootstrap_register(): bootstrap service active"); - break; + if (sharedName == NULL || sharedName == MAP_FAILED) { + jack_error("Allocate: can't check in named futex name = %s err = %s", fName, strerror(errno)); + close(fSharedMem); + fSharedMem = -1; + shm_unlink(fName); + return false; + } - default : - jack_log("bootstrap_register() err = %i:%s", res, mach_error_string(res)); - break; - } + fSharedName = sharedName; + strcpy(fSharedName, fName); - jack_error("Allocate: can't check in mach semaphore name = %s err = %i:%s", fName, res, mach_error_string(res)); + if ((res = semaphore_create(task, &fSemaphore, SYNC_POLICY_FIFO, value)) != KERN_SUCCESS) { + jack_error("Allocate: can create semaphore err = %i:%s", res, mach_error_string(res)); return false; } jack_log("JackMachSemaphore::Allocate name = %s", fName); - return true; + return recursiveBootstrapRegister(1); } // Client side : get the published semaphore from server @@ -170,6 +194,12 @@ bool JackMachSemaphore::ConnectInput(const char* name, const char* server_name) BuildName(name, server_name, fName, sizeof(fName)); kern_return_t res; + // Temporary... + if (fSharedName) { + jack_log("Already connected name = %s", name); + return true; + } + if (fBootPort == 0) { if ((res = task_get_bootstrap_port(mach_task_self(), &fBootPort)) != KERN_SUCCESS) { jack_error("Connect: can't find bootstrap port err = %s", mach_error_string(res)); @@ -177,11 +207,29 @@ bool JackMachSemaphore::ConnectInput(const char* name, const char* server_name) } } - if ((res = bootstrap_look_up(fBootPort, fName, &fSemaphore)) != KERN_SUCCESS) { - jack_error("Connect: can't find mach semaphore name = %s err = %s", fName, mach_error_string(res)); + if ((fSharedMem = shm_open(fName, O_RDWR, 0)) < 0) { + jack_error("Connect: can't connect named futex name = %s err = %s", fName, strerror(errno)); + return false; + } + + char* const sharedName = (char*)mmap(NULL, SYNC_MAX_NAME_SIZE+1, PROT_READ|PROT_WRITE, MAP_SHARED, fSharedMem, 0); + + if (sharedName == NULL || sharedName == MAP_FAILED) { + jack_error("Connect: can't connect named futex name = %s err = %s", fName, strerror(errno)); + close(fSharedMem); + fSharedMem = -1; + return false; + } + + if ((res = bootstrap_look_up(fBootPort, sharedName, &fSemaphore)) != KERN_SUCCESS) { + jack_error("Connect: can't find mach semaphore name = %s, sname = %s, err = %s", fName, sharedName, bootstrap_strerror(res)); + close(fSharedMem); + fSharedMem = -1; return false; } + fSharedName = sharedName; + jack_log("JackMachSemaphore::Connect name = %s ", fName); return true; } @@ -202,7 +250,16 @@ bool JackMachSemaphore::Disconnect() jack_log("JackMachSemaphore::Disconnect name = %s", fName); fSemaphore = 0; } - // Nothing to do + + if (!fSharedName) { + return true; + } + + munmap(fSharedName, SYNC_MAX_NAME_SIZE+1); + fSharedName = NULL; + + close(fSharedMem); + fSharedMem = -1; return true; } @@ -220,6 +277,18 @@ void JackMachSemaphore::Destroy() } else { jack_error("JackMachSemaphore::Destroy semaphore < 0"); } + + if (!fSharedName) { + return; + } + + munmap(fSharedName, SYNC_MAX_NAME_SIZE+1); + fSharedName = NULL; + + close(fSharedMem); + fSharedMem = -1; + + shm_unlink(fName); } } // end of namespace -- 2.11.4.GIT