From d26b791dd215be97f902ff5bd48184c390fbf41d Mon Sep 17 00:00:00 2001 From: Hayodea Hakol Date: Sun, 10 Aug 2025 14:07:27 -0400 Subject: [PATCH] Handle SIGINT (CTL+C) by gracefully shutting down --- smocore/componentThread.cpp | 30 +++++++++++++++++++------ smocore/include/componentThread.h | 2 ++ smocore/include/marionette/marionette.h | 2 ++ smocore/marionette/marionette.cpp | 20 +++++++++++++++++ 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/smocore/componentThread.cpp b/smocore/componentThread.cpp index f08e352..7009d1b 100644 --- a/smocore/componentThread.cpp +++ b/smocore/componentThread.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace smo { @@ -381,13 +382,28 @@ void ComponentThread::exceptionInd(ComponentThread& thread) std::cerr << "Mrntt: Exception occurred: in thread " << thread.name << ". Killing Salmanoff." << "\n"; - smo::mind.finalizeReq( - []() - { - mrntt::mrntt->keepLooping = false; - mrntt::mrntt->getIoService().stop(); - std::cout << "Mrntt: Signaled main loop to exit." << "\n"; - }); + // Delegate to common shutdown request + mind.finalizeReq(smo::mrntt::exitMarionetteLoop); + }); +} + +void ComponentThread::userShutdownInd() +{ + if (this->id != ComponentThread::MRNTT) + { + throw std::runtime_error(std::string(__func__) + + ": invoked on non-mrntt thread " + this->name); + } + + // Post the user shutdown to the mrntt thread. + this->getIoService().post( + []() + { + std::cerr << "Mrntt: User requested shutdown (SIGINT)." + << " Killing Salmanoff." << "\n"; + + // Delegate to common shutdown request + mind.finalizeReq(smo::mrntt::exitMarionetteLoop); }); } diff --git a/smocore/include/componentThread.h b/smocore/include/componentThread.h index 78bb3de..5522e85 100644 --- a/smocore/include/componentThread.h +++ b/smocore/include/componentThread.h @@ -110,6 +110,8 @@ public: // Intentionally doesn't take a callback. void exceptionInd(ComponentThread& thread); + // Intentionally doesn't take a callback. + void userShutdownInd(); public: ThreadId id; diff --git a/smocore/include/marionette/marionette.h b/smocore/include/marionette/marionette.h index af1332c..33acdbd 100644 --- a/smocore/include/marionette/marionette.h +++ b/smocore/include/marionette/marionette.h @@ -13,6 +13,8 @@ class Marionette { }; +void exitMarionetteLoop(); + } // namespace mrntt struct CrtCommandLineArgs diff --git a/smocore/marionette/marionette.cpp b/smocore/marionette/marionette.cpp index f5a0fd0..613c861 100644 --- a/smocore/marionette/marionette.cpp +++ b/smocore/marionette/marionette.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace smo { @@ -19,8 +20,16 @@ void CrtCommandLineArgs::set(int argc, char *argv[], char *envp[]) namespace mrntt { std::atomic exitCode; + +void exitMarionetteLoop() +{ + mrntt::mrntt->keepLooping = false; + mrntt::mrntt->getIoService().stop(); + std::cout << "Mrntt: Signaled main loop to exit." << "\n"; } +} // namespace mrntt + void ComponentThread::marionetteMain(ComponentThread& self) { // Wait for CRT's main() to post us the command line args. @@ -28,8 +37,19 @@ void ComponentThread::marionetteMain(ComponentThread& self) self.getIoService().run(); self.initializeTls(); mrntt::exitCode = EXIT_SUCCESS; + static boost::asio::signal_set signals(self.getIoService(), SIGINT); try { + // Register SIGINT (Ctrl+C) handler to request user shutdown + signals.async_wait( + [&self](const boost::system::error_code& ec, int /*signal*/) + { + if (ec) { return; } + // Post user shutdown indication + self.userShutdownInd(); + } + ); + OptionParser &options = OptionParser::getOptions(); std::cout << __func__ << ": " << PACKAGE_NAME << " " << PACKAGE_VERSION