From 50dfba6905a4047b1ad255daab69e50877a1b3cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Mon, 11 May 2026 16:51:11 +0200 Subject: [PATCH] rewriting receiver using sigwait --- slsReceiverSoftware/src/MultiReceiverApp.cpp | 44 +++++++++----------- slsReceiverSoftware/src/ReceiverApp.cpp | 35 +++++++--------- 2 files changed, 36 insertions(+), 43 deletions(-) diff --git a/slsReceiverSoftware/src/MultiReceiverApp.cpp b/slsReceiverSoftware/src/MultiReceiverApp.cpp index ad6b869ca..51c206907 100644 --- a/slsReceiverSoftware/src/MultiReceiverApp.cpp +++ b/slsReceiverSoftware/src/MultiReceiverApp.cpp @@ -13,7 +13,7 @@ #include //SIGINT #include -#include +#include #include //wait #include @@ -125,18 +125,6 @@ void GetData(slsDetectorDefs::sls_receiver_header &header, // imageSize = 26000; } -sem_t semaphore; - -/** - * Control+C Interrupt Handler - * to let all the processes know to exit properly - * All child processes will call the handler (parent process set to ignore) - */ -void sigInterruptHandler(int signal) { - (void)signal; // suppress unused warning if needed - sem_post(&semaphore); -} - int main(int argc, char *argv[]) { CommandLineOptions cli(AppType::MultiReceiver); @@ -154,13 +142,20 @@ int main(int argc, char *argv[]) { LOG(sls::logINFOBLUE) << "Current Process [ Tid: " << sls::getThreadId() << ']'; - // close files on ctrl+c - sls::setupSignalHandler(SIGINT, sigInterruptHandler); + // Block SIGINT before fork() so every child inherits the block. Each + // child waits for SIGINT synchronously via sigwait() instead of using a + // signal handler that posts to a semaphore. This avoids relying on + // sem_init() on unnamed semaphores, which is unimplemented on macOS. + sigset_t sigset; + sigemptyset(&sigset); + sigaddset(&sigset, SIGINT); + if (pthread_sigmask(SIG_BLOCK, &sigset, nullptr) != 0) { + LOG(sls::logERROR) << "Could not block SIGINT"; + return EXIT_FAILURE; + } // handle locally on socket crash sls::setupSignalHandler(SIGPIPE, SIG_IGN); - sem_init(&semaphore, 1, 0); - /** - loop over receivers */ for (int i = 0; i < m.numReceivers; ++i) { @@ -207,14 +202,15 @@ int main(int argc, char *argv[]) { } /** - as long as no Ctrl+C */ - // each child process gets a copy of the semaphore - sem_wait(&semaphore); - sem_destroy(&semaphore); + // SIGINT is blocked in this child (inherited from parent); + // sigwait atomically waits for it without competing with any + // signal handler. + int sig = 0; + sigwait(&sigset, &sig); LOG(sls::logINFOBLUE) << "Exiting Child Process [ Tid: " << sls::getThreadId() << ']'; exit(EXIT_SUCCESS); } catch (...) { - sem_destroy(&semaphore); LOG(sls::logINFOBLUE) << "Exiting Child Process [ Tid: " << sls::getThreadId() << " ]"; exit(EXIT_FAILURE); @@ -222,9 +218,9 @@ int main(int argc, char *argv[]) { } } - /** - Parent process ignores SIGINT and waits for all the child processes to - * handle the signal */ - sls::setupSignalHandler(SIGINT, SIG_IGN); + /** - Parent process keeps SIGINT blocked (set above before fork) so it is + * never delivered here while waitpid() runs. Each child handles SIGINT + * via sigwait(). */ /** - Print Ready and Instructions how to exit */ std::cout << "Ready ... \n"; diff --git a/slsReceiverSoftware/src/ReceiverApp.cpp b/slsReceiverSoftware/src/ReceiverApp.cpp index b6d38689d..72b388b0c 100644 --- a/slsReceiverSoftware/src/ReceiverApp.cpp +++ b/slsReceiverSoftware/src/ReceiverApp.cpp @@ -11,20 +11,9 @@ #include "sls/sls_detector_defs.h" #include //SIGINT -#include +#include #include -sem_t semaphore; - -/** - * Control+C Interrupt Handler - * to let all the other process know to exit properly - */ -void sigInterruptHandler(int signal) { - (void)signal; // suppress unused warning if needed - sem_post(&semaphore); -} - int main(int argc, char *argv[]) { CommandLineOptions cli(AppType::SingleReceiver); @@ -42,20 +31,28 @@ int main(int argc, char *argv[]) { LOG(sls::logINFOBLUE) << "Current Process [ Tid: " << sls::getThreadId() << " ]"; - // close files on ctrl+c - sls::setupSignalHandler(SIGINT, sigInterruptHandler); + // Block SIGINT on this thread before any other thread is created so that + // every thread spawned by Receiver inherits the block. We wait for the + // signal synchronously with sigwait() further down. This avoids needing a + // signal handler that posts to a semaphore, which is not portable to + // macOS (sem_init on unnamed semaphores is unimplemented there). + sigset_t sigset; + sigemptyset(&sigset); + sigaddset(&sigset, SIGINT); + if (pthread_sigmask(SIG_BLOCK, &sigset, nullptr) != 0) { + LOG(sls::logERROR) << "Could not block SIGINT"; + return EXIT_FAILURE; + } + // handle locally on socket crash sls::setupSignalHandler(SIGPIPE, SIG_IGN); - sem_init(&semaphore, 1, 0); - try { sls::Receiver r(o.port); LOG(sls::logINFO) << "[ Press \'Ctrl+c\' to exit ]"; - sem_wait(&semaphore); - sem_destroy(&semaphore); + int sig = 0; + sigwait(&sigset, &sig); } catch (...) { - sem_destroy(&semaphore); LOG(sls::logINFOBLUE) << "Exiting [ Tid: " << sls::getThreadId() << " ]"; throw;