Skip to content

Commit

Permalink
Add shutdown test. Thanks to @spoonincode
Browse files Browse the repository at this point in the history
  • Loading branch information
heifner committed Sep 27, 2024
1 parent 9a0156a commit d15b6f3
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 5 deletions.
19 changes: 14 additions & 5 deletions application_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ void application_base::startup(boost::asio::io_service& io_serv) {

} catch( ... ) {
clean_up_signal_thread();
shutdown();
shutdown_plugins();
throw;
}

Expand Down Expand Up @@ -441,7 +441,7 @@ void application_base::handle_exception(std::exception_ptr eptr, std::string_vie
}
}

void application_base::shutdown() {
void application_base::shutdown_plugins() {
std::exception_ptr eptr = nullptr;

for(auto ritr = running_plugins.rbegin();
Expand All @@ -454,8 +454,17 @@ void application_base::shutdown() {
handle_exception(std::current_exception(), (*ritr)->name());
}
}
for(auto ritr = running_plugins.rbegin();
ritr != running_plugins.rend(); ++ritr) {

// if we caught an exception while shutting down a plugin, rethrow it so that main()
// can catch it and report the error
if (eptr)
std::rethrow_exception(eptr);
}

void application_base::destroy_plugins() {
std::exception_ptr eptr = nullptr;

for(auto ritr = running_plugins.rbegin(); ritr != running_plugins.rend(); ++ritr) {
try {
plugins.erase((*ritr)->name());
} catch(...) {
Expand All @@ -468,12 +477,12 @@ void application_base::shutdown() {
try {
running_plugins.clear();
initialized_plugins.clear();
plugins.clear();
} catch(...) {
if (!eptr)
eptr = std::current_exception();
handle_exception(std::current_exception(), "plugin cleanup");
}
quit();

// if we caught an exception while shutting down a plugin, rethrow it so that main()
// can catch it and report the error
Expand Down
79 changes: 79 additions & 0 deletions tests/shutdown_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <appbase/application.hpp>
#include <thread>

#include <boost/test/unit_test.hpp>

namespace bpo = boost::program_options;
using bpo::options_description;
using bpo::variables_map;

static bool thing = true;
struct thing_better_be_alive {
~thing_better_be_alive() noexcept(false) {
if(!thing)
throw "BOOM";
}
};

class thready_plugin : public appbase::plugin<thready_plugin> {
public:

template <typename Lambda>
void plugin_requires(Lambda&& l) {}

void set_program_options( options_description& cli, options_description& cfg ) override {}

void thread_work() {
boost::asio::post(ctx, [&]() {
thing_better_be_alive better_be;
boost::asio::post(appbase::app().get_io_service(), [&,is_it=std::move(better_be)]() {
thread_work();
});
});
}

void plugin_initialize( const variables_map& options ) {}
void plugin_startup() {
for(unsigned i = 0; i < 48*4; i++)
thread_work();

for(unsigned i = 0; i < 48; ++i)
threads.emplace_back([this]() {
ctx.run();
});
}
void plugin_shutdown() {
usleep(100000); //oh gee it takes a while to stop
ctx.stop();
for(unsigned i = 0; i < 48; ++i)
threads[i].join();
}

~thready_plugin() {
thing = false;
}

boost::asio::io_context ctx;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> wg = boost::asio::make_work_guard(ctx);

private:
std::vector<std::thread> threads;
};


BOOST_AUTO_TEST_CASE(test_shutdown)
{
appbase::application::register_plugin<thready_plugin>();
appbase::scoped_app app;

const char* argv[] = { "nodoes" };
if( !app->initialize<thready_plugin>( 1, const_cast<char**>(argv) ) )
return;
app->startup();
boost::asio::post(appbase::app().get_io_service(), [&](){
std::this_thread::sleep_for(std::chrono::milliseconds(5));
app->quit();
});
app->exec();

}

0 comments on commit d15b6f3

Please sign in to comment.