main: re-read configuration file on SIGHUP
Trap SIGHUP and signal a loop to re-read the configuration file.
This commit is contained in:
68
main.cc
68
main.cc
@@ -146,6 +146,69 @@ read_config(bpo::variables_map& opts, db::config& cfg) {
|
||||
return make_exception_future<>(ep);
|
||||
});
|
||||
}
|
||||
|
||||
// Handles SIGHUP, using it to trigger re-reading of the configuration file. Should
|
||||
// only be constructed on shard 0.
|
||||
class sighup_handler {
|
||||
bpo::variables_map& _opts;
|
||||
db::config& _cfg;
|
||||
condition_variable _cond;
|
||||
bool _pending = false; // if asked to reread while already reading
|
||||
bool _stopping = false;
|
||||
future<> _done = do_work(); // Launch main work loop, capture completion future
|
||||
public:
|
||||
// Installs the signal handler. Must call stop() (and wait for it) before destruction.
|
||||
sighup_handler(bpo::variables_map& opts, db::config& cfg) : _opts(opts), _cfg(cfg) {
|
||||
startlog.info("installing SIGHUP handler");
|
||||
engine().handle_signal(SIGHUP, [this] { reread_config(); });
|
||||
}
|
||||
private:
|
||||
void reread_config() {
|
||||
if (_stopping) {
|
||||
return;
|
||||
}
|
||||
_pending = true;
|
||||
_cond.broadcast();
|
||||
}
|
||||
// Main work loop. Waits for either _stopping or _pending to be raised, and
|
||||
// re-reads the configuration file if _pending. We use a repeat loop here to
|
||||
// avoid having multiple reads of the configuration file happening in parallel
|
||||
// (this can cause an older read to overwrite the results of a younger read).
|
||||
future<> do_work() {
|
||||
return repeat([this] {
|
||||
return _cond.wait([this] { return _pending || _stopping; }).then([this] {
|
||||
return async([this] {
|
||||
if (_stopping) {
|
||||
return stop_iteration::yes;
|
||||
} else if (_pending) {
|
||||
_pending = false;
|
||||
try {
|
||||
startlog.info("re-reading configuration file");
|
||||
read_config(_opts, _cfg).get();
|
||||
_cfg.broadcast_to_all_shards().get();
|
||||
startlog.info("completed re-reading configuration file");
|
||||
} catch (...) {
|
||||
startlog.error("failed to re-read configuration file: {}", std::current_exception());
|
||||
}
|
||||
}
|
||||
return stop_iteration::no;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
public:
|
||||
// Signals the main work loop to stop, and waits for it (and any in-progress work)
|
||||
// to complete. After this is waited for, the object can be destroyed.
|
||||
future<> stop() {
|
||||
// No way to unregister yet
|
||||
engine().handle_signal(SIGHUP, [] {});
|
||||
_pending = false;
|
||||
_stopping = true;
|
||||
_cond.broadcast();
|
||||
return std::move(_done);
|
||||
}
|
||||
};
|
||||
|
||||
static future<> disk_sanity(sstring path, bool developer_mode) {
|
||||
return check_direct_io_support(path).then([] {
|
||||
return make_ready_future<>();
|
||||
@@ -408,6 +471,11 @@ int main(int ac, char** av) {
|
||||
configurable::init_all(opts, *cfg, *ext).get();
|
||||
cfg->broadcast_to_all_shards().get();
|
||||
|
||||
::sighup_handler sigup_handler(opts, *cfg);
|
||||
auto stop_sighup_handler = defer([&] {
|
||||
sigup_handler.stop().get();
|
||||
});
|
||||
|
||||
logalloc::prime_segment_pool(memory::stats().total_memory(), memory::min_free_memory()).get();
|
||||
logging::apply_settings(cfg->logging_settings(opts));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user