From 2f1231d185d637215012794b3bd4277214e1df4b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 17 Mar 2026 19:26:32 -0700 Subject: [PATCH] macOS Semaphore Cleanup macOS uses GCD for threading and semaphores, but they aren't quite like POSIX semaphores. macOS allows the use of named POSIX semaphores. 1. Convert the semaphores to named POSIX semaphores. 2. Simplify all calls for semaphores into single function calls of the wrapper API. 3. Update both examples/client/client.c and apps/wolfssh/wolfssh.c. 4. Update both to deregister the WINCH signal. --- apps/wolfssh/wolfssh.c | 99 +++++++++++++++++++++++++++------------- examples/client/client.c | 99 +++++++++++++++++++++++++++------------- 2 files changed, 136 insertions(+), 62 deletions(-) diff --git a/apps/wolfssh/wolfssh.c b/apps/wolfssh/wolfssh.c index 6efbece30..f333bfb95 100644 --- a/apps/wolfssh/wolfssh.c +++ b/apps/wolfssh/wolfssh.c @@ -272,22 +272,70 @@ static int sendCurrentWindowSize(thread_args* args) #ifndef _MSC_VER -#if (defined(__OSX__) || defined(__APPLE__)) -#include -dispatch_semaphore_t windowSem; -#else +#include +#include #include -static sem_t windowSem; -#endif +#include +#include + +typedef struct { + sem_t* s; + char name[32]; +} WOLFSSH_SEMAPHORE; + +static inline +int wolfSSH_SEMAPHORE_Init(WOLFSSH_SEMAPHORE* s, unsigned int n) +{ + if (s != NULL) { + snprintf(s->name, sizeof(s->name), "/wolfssh_winch_%d", (int)getpid()); + s->s = sem_open(s->name, O_CREAT | O_EXCL | O_RDWR, 0600, n); + if (s->s == SEM_FAILED && errno == EEXIST) { + /* named semaphore already exists, unlink the name and + * try to open it one more time. */ + if (sem_unlink(s->name) == 0) { + s->s = sem_open(s->name, O_CREAT | O_RDWR, 0600, n); + } + } + } + return (s != NULL && s->s != SEM_FAILED); +} + +static inline +void wolfSSH_SEMAPHORE_Release(WOLFSSH_SEMAPHORE* s) +{ + if (s != NULL && s->s != NULL && s->s != SEM_FAILED) { + sem_close(s->s); + sem_unlink(s->name); + s->s = NULL; + } +} + +static inline +int wolfSSH_SEMAPHORE_Wait(WOLFSSH_SEMAPHORE* s) +{ + int ret = -1; + if (s != NULL && s->s != NULL && s->s != SEM_FAILED) { + do { + ret = sem_wait(s->s); + } while (ret == -1 && errno == EINTR); + } + return (ret == 0); +} + +static inline +void wolfSSH_SEMAPHORE_Post(WOLFSSH_SEMAPHORE* s) +{ + if (s != NULL && s->s != NULL && s->s != SEM_FAILED) { + sem_post(s->s); + } +} + +static WOLFSSH_SEMAPHORE windowSem; /* capture window change signals */ static void WindowChangeSignal(int sig) { -#if (defined(__OSX__) || defined(__APPLE__)) - dispatch_semaphore_signal(windowSem); -#else - sem_post(&windowSem); -#endif + wolfSSH_SEMAPHORE_Post(&windowSem); (void)sig; } @@ -299,11 +347,9 @@ static THREAD_RET windowMonitor(void* in) args = (thread_args*)in; do { - #if (defined(__OSX__) || defined(__APPLE__)) - dispatch_semaphore_wait(windowSem, DISPATCH_TIME_FOREVER); - #else - sem_wait(&windowSem); - #endif + if (!wolfSSH_SEMAPHORE_Wait(&windowSem)) { + break; + } if (args->quit) { break; } @@ -1060,11 +1106,9 @@ static THREAD_RETURN WOLFSSH_THREAD wolfSSH_Client(void* args) arg.readError = 0; #ifdef WOLFSSH_TERM arg.quit = 0; - #if (defined(__OSX__) || defined(__APPLE__)) - windowSem = dispatch_semaphore_create(0); - #else - sem_init(&windowSem, 0, 0); - #endif + if (!wolfSSH_SEMAPHORE_Init(&windowSem, 0)) { + err_sys("Couldn't initialize window semaphore."); + } if (config.command) { int err; @@ -1087,21 +1131,14 @@ static THREAD_RETURN WOLFSSH_THREAD wolfSSH_Client(void* args) #ifdef WOLFSSH_TERM /* Wake the windowMonitor thread so it can exit. */ arg.quit = 1; - #if (defined(__OSX__) || defined(__APPLE__)) - dispatch_semaphore_signal(windowSem); - #else - sem_post(&windowSem); - #endif + signal(SIGWINCH, SIG_DFL); + wolfSSH_SEMAPHORE_Post(&windowSem); pthread_join(thread[0], NULL); #endif /* WOLFSSH_TERM */ pthread_cancel(thread[1]); pthread_join(thread[1], NULL); #ifdef WOLFSSH_TERM - #if (defined(__OSX__) || defined(__APPLE__)) - dispatch_release(windowSem); - #else - sem_destroy(&windowSem); - #endif + wolfSSH_SEMAPHORE_Release(&windowSem); #endif /* WOLFSSH_TERM */ ioErr = arg.readError; #elif defined(_MSC_VER) diff --git a/examples/client/client.c b/examples/client/client.c index 6124c7a90..a6f3a7bef 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -240,22 +240,70 @@ static int sendCurrentWindowSize(thread_args* args) #ifdef WOLFSSH_TERM #ifndef _MSC_VER -#if (defined(__OSX__) || defined(__APPLE__)) -#include -dispatch_semaphore_t windowSem; -#else +#include +#include #include -static sem_t windowSem; -#endif +#include +#include + +typedef struct { + sem_t* s; + char name[32]; +} WOLFSSH_SEMAPHORE; + +static inline +int wolfSSH_SEMAPHORE_Init(WOLFSSH_SEMAPHORE* s, unsigned int n) +{ + if (s != NULL) { + snprintf(s->name, sizeof(s->name), "/wolfssh_winch_%d", (int)getpid()); + s->s = sem_open(s->name, O_CREAT | O_EXCL | O_RDWR, 0600, n); + if (s->s == SEM_FAILED && errno == EEXIST) { + /* named semaphore already exists, unlink the name and + * try to open it one more time. */ + if (sem_unlink(s->name) == 0) { + s->s = sem_open(s->name, O_CREAT | O_RDWR, 0600, n); + } + } + } + return (s != NULL && s->s != SEM_FAILED); +} + +static inline +void wolfSSH_SEMAPHORE_Release(WOLFSSH_SEMAPHORE* s) +{ + if (s != NULL && s->s != NULL && s->s != SEM_FAILED) { + sem_close(s->s); + sem_unlink(s->name); + s->s = NULL; + } +} + +static inline +int wolfSSH_SEMAPHORE_Wait(WOLFSSH_SEMAPHORE* s) +{ + int ret = -1; + if (s != NULL && s->s != NULL && s->s != SEM_FAILED) { + do { + ret = sem_wait(s->s); + } while (ret == -1 && errno == EINTR); + } + return (ret == 0); +} + +static inline +void wolfSSH_SEMAPHORE_Post(WOLFSSH_SEMAPHORE* s) +{ + if (s != NULL && s->s != NULL && s->s != SEM_FAILED) { + sem_post(s->s); + } +} + +static WOLFSSH_SEMAPHORE windowSem; /* capture window change signals */ static void WindowChangeSignal(int sig) { -#if (defined(__OSX__) || defined(__APPLE__)) - dispatch_semaphore_signal(windowSem); -#else - sem_post(&windowSem); -#endif + wolfSSH_SEMAPHORE_Post(&windowSem); (void)sig; } @@ -267,11 +315,9 @@ static THREAD_RET windowMonitor(void* in) args = (thread_args*)in; do { - #if (defined(__OSX__) || defined(__APPLE__)) - dispatch_semaphore_wait(windowSem, DISPATCH_TIME_FOREVER); - #else - sem_wait(&windowSem); - #endif + if (!wolfSSH_SEMAPHORE_Wait(&windowSem)) { + break; + } if (args->quit) { break; } @@ -1032,11 +1078,9 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) arg.quit = 0; wc_InitMutex(&arg.lock); #ifdef WOLFSSH_TERM - #if (defined(__OSX__) || defined(__APPLE__)) - windowSem = dispatch_semaphore_create(0); - #else - sem_init(&windowSem, 0, 0); - #endif + if (!wolfSSH_SEMAPHORE_Init(&windowSem, 0)) { + err_sys("Couldn't initialize window semaphore."); + } if (cmd) { int err; @@ -1057,21 +1101,14 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) #ifdef WOLFSSH_TERM /* Wake the windowMonitor thread so it can exit. */ arg.quit = 1; - #if (defined(__OSX__) || defined(__APPLE__)) - dispatch_semaphore_signal(windowSem); - #else - sem_post(&windowSem); - #endif + signal(SIGWINCH, SIG_DFL); + wolfSSH_SEMAPHORE_Post(&windowSem); pthread_join(thread[0], NULL); #endif /* WOLFSSH_TERM */ pthread_cancel(thread[1]); pthread_join(thread[1], NULL); #ifdef WOLFSSH_TERM - #if (defined(__OSX__) || defined(__APPLE__)) - dispatch_release(windowSem); - #else - sem_destroy(&windowSem); - #endif + wolfSSH_SEMAPHORE_Release(&windowSem); #endif /* WOLFSSH_TERM */ #elif defined(_MSC_VER) thread_args arg;