#include #include #include #include #include #include #include #include #include #include #include namespace smo { namespace mrntt { std::shared_ptr thread = std::make_shared< sscl::PuppeteerThread>( SmoThreadId::MRNTT, smo::getThreadName(SmoThreadId::MRNTT), sscl::pptr::PuppeteerComponent::defaultPuppeteerMain, mrntt, &MarionetteComponent::preJoltHook); MarionetteComponent mrntt(thread); void marionetteInitializeReqCb(bool success) { if (success) { std::cout << __func__ << ": Marionette initialized." << '\n'; return; } std::cerr << __func__ << ": Failed to initialize Marionette. Shutting down." << '\n'; mrntt.holdFinalizeCReq( []() { marionetteFinalizeReqCb(true); }); } void marionetteFinalizeReqCb(bool success) { if (!success) { std::cerr << __func__ << ": Failed to finalize Marionette." << '\n'; // Fallthrough. } std::cout << __func__ << ": Marionette finalized." << '\n'; thread->exitLoop(); } void MarionetteComponent::preJoltHook(sscl::PuppeteerThread &self) { sscl::pptr::exitCode = EXIT_SUCCESS; pthread_setname_np(pthread_self(), self.name.c_str()); std::cout << __func__ << ": Waiting for command line JOLT" << std::endl; } void MarionetteComponent::postJoltHook() { auto th = smo::mrntt::thread; callShutdownSalmanoff = false; // Register SIGINT (Ctrl+C) and SIGSEGV handlers signals = std::make_unique( th->getIoContext(), SIGINT); signals->async_wait( [](const boost::system::error_code& ec, int signal) { if (ec) { return; } switch (signal) { case SIGINT: std::cerr << "SIGINT (Ctrl+C) received. Initiating " "shutdown..." << '\n'; break; case SIGSEGV: std::cerr << "FATAL: Segmentation fault detected. " "Initiating shutdown..." << '\n'; break; default: break; } mrntt.holdFinalizeCReq( []() { marionetteFinalizeReqCb(true); }); }); } void MarionetteComponent::tryBlock1Hook() { OptionParser &options = OptionParser::getOptions(); std::cout << "PuppeteerThread::main: " << PACKAGE_NAME << " " << PACKAGE_VERSION << std::endl; options.parseArguments( sscl::crtCommandLineArgs.argc, sscl::crtCommandLineArgs.argv, sscl::crtCommandLineArgs.envp); std::cout << "PuppeteerThread::main: " << options.stringifyOptions() << std::endl; if (options.printUsage) { throw JustPrintUsageNoError(options); } } void MarionetteComponent::preLoopHook() { /** EXPLANATION: * Initialize Salmanoff's Manager classes first. * Manager classes' initialization is synchronous in nature, so we * don't need the minds to be running to initialize them. * * Then we initialize the Minds. Minds are asynchronous and they * call upon the async methods of the Manager classes. Device * attachment is actually Mind specific and not Smo-global * * It is arguable whether library loading is Mind specific or * Smo-global. You could argue that libraries should be loaded and * unloaded dynamically as-needed by the bodies and worlds of * particular Minds. You could also argue that we should load all * libraries at startup and unload them at shutdown. * * The latter is cleaner and more resource-respecting. The former is * easier to implement. */ smo::initializeSalmanoff(); callShutdownSalmanoff = true; holdInitializeCReq( [] { marionetteInitializeReqCb( mrntt.initializeLifetimeSucceeded && !mrntt.initializeLifetimeExceptionPtr); }); std::cout << "PuppeteerThread::main: Entering event loop" << "\n"; } void MarionetteComponent::postLoopHook() { std::cout << "PuppeteerThread::main: Exited event loop" << "\n"; } void MarionetteComponent::postTryBlock1CatchHook() { if (callShutdownSalmanoff) { smo::shutdownSalmanoff(); } } void MarionetteComponent::handleTryBlock1TypedException(const std::exception& e) { const OptionParser::Exception* optEx = dynamic_cast(&e); if (optEx) { std::ostream *out = &std::cout; std::string outUsageMsg; if (typeid(*optEx) == typeid(OptionsParserError)) { sscl::pptr::exitCode = EXIT_FAILURE; out = &std::cerr; outUsageMsg = std::string("main: ") + ": "; } // Else it's a JustPrintUsageNoError. *out << outUsageMsg << optEx->what() << std::endl; return; } std::cerr << "main: Exception occurred: " << e.what() << std::endl; sscl::pptr::exitCode = EXIT_FAILURE; } void MarionetteComponent::handleTryBlock1UnknownException() { std::cerr << "main: Unknown exception occurred" << std::endl; sscl::pptr::exitCode = EXIT_FAILURE; } } // namespace mrntt } // namespace smo