From ef8d8a5fd297bbe707f5f8cd98e678e5899f1a74 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 9 Jul 2025 17:19:54 +0200 Subject: [PATCH] raising a SIGINT when the child thread has an exception so that the parent thread can exit all the threads and clean up gracefully --- .../src/FrameSynchronizerApp.cpp | 64 +++++++++++-------- slsReceiverSoftware/src/Receiver.cpp | 3 + 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/slsReceiverSoftware/src/FrameSynchronizerApp.cpp b/slsReceiverSoftware/src/FrameSynchronizerApp.cpp index 1fa2f3fb1..69d85534a 100644 --- a/slsReceiverSoftware/src/FrameSynchronizerApp.cpp +++ b/slsReceiverSoftware/src/FrameSynchronizerApp.cpp @@ -541,45 +541,44 @@ int main(int argc, char *argv[]) { void *user_data = static_cast(&stat); std::thread combinerThread(Correlate, &stat); + std::exception_ptr threadException = nullptr; for (int i = 0; i != f.numReceivers; ++i) { uint16_t port = f.port + i; sem_t *semaphore = &semaphores[i]; - threads.emplace_back([i, semaphore, port, user_data]() { - LOG(sls::logINFOBLUE) - << "Thread " << i << " [ Tid: " << gettid() << ']'; - try { - sls::Receiver receiver(port); - receiver.registerCallBackStartAcquisition( - StartAcquisitionCallback, user_data); - receiver.registerCallBackAcquisitionFinished( - AcquisitionFinishedCallback, user_data); - receiver.registerCallBackRawDataReady(GetDataCallback, - user_data); + threads.emplace_back( + [i, semaphore, port, user_data, &threadException]() { + LOG(sls::logINFOBLUE) + << "Thread " << i << " [ Tid: " << gettid() << ']'; + try { + sls::Receiver receiver(port); + receiver.registerCallBackStartAcquisition( + StartAcquisitionCallback, user_data); + receiver.registerCallBackAcquisitionFinished( + AcquisitionFinishedCallback, user_data); + receiver.registerCallBackRawDataReady(GetDataCallback, + user_data); - /** - as long as no Ctrl+C */ - // each child shares the common semaphore - sem_wait(semaphore); - } catch (...) { + /** - as long as no Ctrl+C */ + // each child shares the common semaphore + sem_wait(semaphore); + } catch (...) { + // capture exception and raise SIGINT to exit gracefully + threadException = std::current_exception(); + raise(SIGINT); + } LOG(sls::logINFOBLUE) << "Exiting Thread " << i << " [ Tid: " << gettid() << " ]"; - for (auto &s : semaphores) - sem_destroy(&s); - cleanup(); - if (global_frame_status) - sem_destroy(&(global_frame_status->available)); - std::exit(EXIT_FAILURE); - } - LOG(sls::logINFOBLUE) - << "Exiting Thread " << i << " [ Tid: " << gettid() << " ]"; - sem_destroy(semaphore); - }); + }); } for (auto &t : threads) { t.join(); } + for (auto &s : semaphores) + sem_destroy(&s); cleanup(); + { std::lock_guard lock(stat.mtx); stat.terminate = true; @@ -588,6 +587,19 @@ int main(int argc, char *argv[]) { combinerThread.join(); sem_destroy(&stat.available); + if (threadException) { + try { + std::rethrow_exception(threadException); + } catch (const std::exception &e) { + LOG(sls::logERROR) + << "Unhandled exception from thread: " << e.what(); + return EXIT_FAILURE; + } catch (...) { + LOG(sls::logERROR) << "Unknown exception occurred in thread"; + return EXIT_FAILURE; + } + } + LOG(sls::logINFOBLUE) << "Goodbye!"; return EXIT_SUCCESS; } diff --git a/slsReceiverSoftware/src/Receiver.cpp b/slsReceiverSoftware/src/Receiver.cpp index d81ecb33a..84bcd485d 100644 --- a/slsReceiverSoftware/src/Receiver.cpp +++ b/slsReceiverSoftware/src/Receiver.cpp @@ -29,6 +29,9 @@ Receiver::~Receiver() = default; Receiver::Receiver(uint16_t port) { validatePortNumber(port); + if (port == 9999) { + throw sls::RuntimeError("Throwing for testing purposes. "); + } tcpipInterface = make_unique(port); }