From e276fcbdce9641aa176b807cec84df316339cbfe Mon Sep 17 00:00:00 2001 From: Hayodea Hakol Date: Wed, 30 Jul 2025 09:09:38 -0400 Subject: [PATCH] Mrntt: use keepLooping after exception; Mind: split code from mrntt Mrntt now has the event loop structure required to orderly shut itself down when it itself generates an exception. We can now post a message within the catch{} blocks for Mrntt's event loop, telling Mrntt to shut down the Mind threads and then shut itself down. We also split the code to initialize threads etc out of mrntt and put it into the Mind:: namespace. --- smocore/componentThread.cpp | 11 +++- smocore/include/marionette/marionette.h | 2 +- smocore/include/mind.h | 1 + smocore/marionette/marionette.cpp | 70 +++++++++++++++---------- smocore/marionette/salmanoff.cpp | 3 +- smocore/mind.cpp | 23 ++++++++ 6 files changed, 79 insertions(+), 31 deletions(-) diff --git a/smocore/componentThread.cpp b/smocore/componentThread.cpp index dc87253..46a3586 100644 --- a/smocore/componentThread.cpp +++ b/smocore/componentThread.cpp @@ -96,6 +96,13 @@ void ComponentThread::main(ComponentThread& self) std::cout << self.name << ":" << __func__ << ": Entering event loop" <<"\n"; + /* We loop here because when an exception is caught, we need to first catch + * it in the catch blocks. We bubble the exception to mrntt in the catch + * blocks, and then we loop here to await control messages from mrntt. + * + * We can't just exit on our own. Rather, we must wait for mrntt to tell us + * to exit. When we wish to finally exit, we set keepLooping to false. + */ for (self.keepLooping = true; self.keepLooping;) { try { @@ -118,7 +125,7 @@ void ComponentThread::main(ComponentThread& self) } } - std::cout << self.name << ":" << __func__ << ": Exiting event loop" << "\n"; + std::cout << self.name << ":" << __func__ << ": Exited event loop" << "\n"; } // Thread management method implementations @@ -245,6 +252,8 @@ void ComponentThread::exceptionInd(ComponentThread& thread) currThreadJ->thread.join(); } + + mrntt::mrntt->keepLooping = false; mrntt::mrntt->getIoService().stop(); } ); diff --git a/smocore/include/marionette/marionette.h b/smocore/include/marionette/marionette.h index ec0c1e3..50b3a23 100644 --- a/smocore/include/marionette/marionette.h +++ b/smocore/include/marionette/marionette.h @@ -28,7 +28,7 @@ struct CrtCommandLineArgs static void set(int argc, char *argv[], char *envp[]); }; -int initializeSalmanoff(void); +void initializeSalmanoff(void); } // namespace smo diff --git a/smocore/include/mind.h b/smocore/include/mind.h index 9d7a74e..a270676 100644 --- a/smocore/include/mind.h +++ b/smocore/include/mind.h @@ -12,6 +12,7 @@ namespace smo { class Mind { public: + void initialize(void); void execute(void); public: diff --git a/smocore/marionette/marionette.cpp b/smocore/marionette/marionette.cpp index 40a69ea..d815622 100644 --- a/smocore/marionette/marionette.cpp +++ b/smocore/marionette/marionette.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -57,37 +58,52 @@ void ComponentThread::marionetteMain(ComponentThread& self) return; } - int ret = smo::initializeSalmanoff(); - if (ret != 0) + smo::Mind mind; + + self.getIoService().post([&mind]() { - std::cerr << __func__ << ": Initialization failed with code: " - << ret << std::endl; - mrntt::exitCode = ret; - return; - } + try { + initializeSalmanoff(); + mind.initialize(); + } + catch (const std::exception& e) { + mrntt::exitCode = EXIT_FAILURE; + throw; + } - /* Start the threads */ - for (auto& componentThread : smo::ComponentThread::componentThreads) - { - // Post startThread() to the event loop of all threads except MRNTT. - if (componentThread->id == ComponentThread::MRNTT) { continue; } - - // JOLT the thread. - componentThread->getIoService().post([componentThread]() - { componentThread->getIoService().stop(); } - ); - - // Now tell it to execute its initialization sequence. - componentThread->startThreadReq(); - } - - body::body->getIoService().post([]{ - throw std::runtime_error("test exception"); - }); + body::body->getIoService().post([]{ + throw std::runtime_error("test exception"); + }); + }); std::cout << __func__ << ": Entering event loop" << "\n"; - self.getIoService().reset(); - self.getIoService().run(); + + /* We loop here because when an exception occurs in mrntt, we need to + * both direct the mind threads to exit gracefully, and then we also + * need to post messages to our own event loop to initiate our own + * orderly exit. So we loop here to re-enter the event loop, both + * to receive the ACK messages from the mind threads, and to post + * messages to our own event loop to initiate our own orderly exit. + */ + for (self.keepLooping = true; self.keepLooping;) + { + try { + self.getIoService().reset(); + self.getIoService().run(); + } + catch (const std::exception& e) + { + std::cerr << self.name << ":" << __func__ + << ": Exception occurred: " << e.what() << "\n"; + } + catch (...) + { + std::cerr << self.name << ":" << __func__ + << ": Unknown exception occurred" << "\n"; + } + } + + std::cout << __func__ << ": Exited event loop" << "\n"; } catch (const std::exception& e) { diff --git a/smocore/marionette/salmanoff.cpp b/smocore/marionette/salmanoff.cpp index 9a74126..1434c83 100644 --- a/smocore/marionette/salmanoff.cpp +++ b/smocore/marionette/salmanoff.cpp @@ -4,7 +4,7 @@ namespace smo { -int initializeSalmanoff(void) +void initializeSalmanoff(void) { std::cout << __func__ << ": Entered." << std::endl; @@ -21,7 +21,6 @@ std::cerr << "About to attachAllSenseDevicesFromSpecs" << std::endl; std::cerr << "Done attachAllSenseDevicesFromSpecs" << std::endl; std::cout << __func__ << ": Done." << std::endl; - return 0; } } // namespace smo diff --git a/smocore/mind.cpp b/smocore/mind.cpp index 38d08ed..64d17ea 100644 --- a/smocore/mind.cpp +++ b/smocore/mind.cpp @@ -1,2 +1,25 @@ #include +#include + +namespace smo { + +void Mind::initialize() +{ + /* Start the threads */ + for (auto& componentThread : smo::ComponentThread::componentThreads) + { + // Post startThread() to the event loop of all threads except MRNTT. + if (componentThread->id == ComponentThread::MRNTT) { continue; } + + // JOLT the thread. + componentThread->getIoService().post([componentThread]() + { componentThread->getIoService().stop(); } + ); + + // Now tell it to execute its initialization sequence. + componentThread->startThreadReq(); + } +} + +} // namespace smo