b6b2ce7ada
This is generally frowned upon but it makes this code 10x cleaner. We handle commandLine usage msg printing by using exceptions for control flow. This allows us to centralize the logic for killing the Mind threads in one place. At least with respect to printing the usage msg.
152 lines
3.9 KiB
C++
152 lines
3.9 KiB
C++
#include <config.h>
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
#include <exception>
|
|
#include <opts.h>
|
|
#include <mind.h>
|
|
#include <componentThread.h>
|
|
#include <marionette/marionette.h>
|
|
#include <salmanoff.h>
|
|
#include <boost/asio/signal_set.hpp>
|
|
#include <typeinfo>
|
|
|
|
namespace smo {
|
|
|
|
CrtCommandLineArgs crtCommandLineArgs(0, nullptr, nullptr);
|
|
|
|
void CrtCommandLineArgs::set(int argc, char *argv[], char *envp[])
|
|
{
|
|
crtCommandLineArgs = CrtCommandLineArgs(argc, argv, envp);
|
|
}
|
|
|
|
namespace mrntt {
|
|
std::atomic<int> 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.
|
|
std::cout << __func__ << ": Waiting for command line JOLT" << std::endl;
|
|
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
|
|
<< std::endl;
|
|
|
|
options.parseArguments(
|
|
crtCommandLineArgs.argc, crtCommandLineArgs.argv,
|
|
crtCommandLineArgs.envp);
|
|
|
|
std::cout << __func__ << ": " << options.stringifyOptions()
|
|
<< std::endl;
|
|
|
|
if (options.printUsage) {
|
|
throw JustPrintUsageNoError(options);
|
|
}
|
|
|
|
self.getIoService().post([]()
|
|
{
|
|
initializeSalmanoff();
|
|
mind.initialize();
|
|
});
|
|
|
|
std::cout << __func__ << ": Entering event loop" << "\n";
|
|
|
|
/* 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;)
|
|
{
|
|
bool sendExceptionInd = false;
|
|
try {
|
|
self.getIoService().reset();
|
|
self.getIoService().run();
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
sendExceptionInd = true;
|
|
std::cerr << self.name << ":" << __func__
|
|
<< ": Exception occurred: " << e.what() << "\n";
|
|
}
|
|
catch (...)
|
|
{
|
|
sendExceptionInd = true;
|
|
std::cerr << self.name << ":" << __func__
|
|
<< ": Unknown exception occurred" << "\n";
|
|
}
|
|
|
|
if (sendExceptionInd)
|
|
{
|
|
mrntt::exitCode = EXIT_FAILURE;
|
|
self.exceptionInd(self);
|
|
}
|
|
}
|
|
|
|
std::cout << __func__ << ": Exited event loop" << "\n";
|
|
shutdownSalmanoff();
|
|
}
|
|
catch (const OptionParser::Exception& e)
|
|
{
|
|
std::ostream &out = std::cout;
|
|
std::string outUsageMsg;
|
|
|
|
if (typeid(e) == typeid(OptionsParserError))
|
|
{
|
|
mrntt::exitCode = EXIT_FAILURE;
|
|
outUsageMsg = std::string(__func__) + ": ";
|
|
}
|
|
|
|
out << outUsageMsg << e.what() << std::endl;
|
|
mind.finalizeReq([]{
|
|
mrntt::mrntt->getIoService().stop();
|
|
});
|
|
self.getIoService().reset();
|
|
self.getIoService().run();
|
|
return;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cerr << __func__ << ": Exception occurred: " << e.what()
|
|
<< std::endl;
|
|
mrntt::exitCode = EXIT_FAILURE;
|
|
return;
|
|
}
|
|
catch (...)
|
|
{
|
|
std::cerr << __func__ << ": Unknown exception occurred" << std::endl;
|
|
mrntt::exitCode = EXIT_FAILURE;
|
|
return;
|
|
}
|
|
|
|
std::cout << __func__ << ": Exiting normally" << std::endl;
|
|
}
|
|
|
|
} // namespace smo
|