Files
scylladb/core/app-template.cc
Tomasz Grabiec 8a126b9088 core: Fix use-after-free error on _threads
When smp::configure() is called from non-main thread, then the global
state which it allocates will be destroyed after reactor is destroyed,
because it will be destroyed from the main thread and the reactor will
be destroyed together with the thread which called
smp::configure(). This will result in SIGSEGV when allocator tries to
free _threads vector across CPU threads because the target CPU was
alrady freed. See issue #10.

To fix this, I introduced smp::cleanup() method which should cleanup
all global state and should be called in the same thread in which
smp::configure() was called.

I need to call smp::configure() from non-main thread for integration
with boost unit testing framework.
2015-01-28 16:18:53 +02:00

79 lines
2.1 KiB
C++

/*
* Copyright (C) 2014 Cloudius Systems, Ltd.
*/
#include "app-template.hh"
#include "core/reactor.hh"
#include "core/scollectd.hh"
#include "core/print.hh"
#include <boost/program_options.hpp>
#include <fstream>
#include <cstdlib>
namespace bpo = boost::program_options;
app_template::app_template()
: _opts("App options") {
_opts.add_options()
("help,h", "show help message")
;
_opts.add(reactor::get_options_description());
_opts.add(smp::get_options_description());
_opts.add(scollectd::get_options_description());
}
boost::program_options::options_description_easy_init
app_template::add_options() {
return _opts.add_options();
}
bpo::variables_map&
app_template::configuration() {
return *_configuration;
}
int
app_template::run(int ac, char ** av, std::function<void ()>&& func) {
#ifdef DEBUG
print("WARNING: debug mode. Not for benchmarking or production\n");
#endif
bpo::variables_map configuration;
try {
bpo::store(bpo::command_line_parser(ac, av).options(_opts).run(), configuration);
auto home = std::getenv("HOME");
if (home) {
std::ifstream ifs(std::string(home) + "/.config/seastar/seastar.conf");
if (ifs) {
bpo::store(bpo::parse_config_file(ifs, _opts), configuration);
}
}
} catch (bpo::error& e) {
print("error: %s\n\nTry --help.\n", e.what());
return 2;
}
bpo::notify(configuration);
if (configuration.count("help")) {
std::cout << _opts << "\n";
return 1;
}
smp::configure(configuration);
_configuration = {std::move(configuration)};
engine().when_started().then([this] {
scollectd::configure( this->configuration());
}).then(
std::move(func)
).rescue([] (auto get_ex) {
try {
get_ex();
} catch (std::exception& ex) {
std::cout << "program failed with uncaught exception: " << ex.what() << "\n";
engine().exit(1);
}
});
auto exit_code = engine().run();
smp::cleanup();
return exit_code;
}