diff --git a/construct/construct.cc b/construct/construct.cc index 9d038adb0..ebbab00a1 100644 --- a/construct/construct.cc +++ b/construct/construct.cc @@ -108,6 +108,7 @@ const char *const usererrstr *** )"}; +[[noreturn]] static void do_restart(char *const *const &argv, char *const *const &envp); static bool startup_checks(); static void applyargs(); static void enable_coredumps(); @@ -375,7 +376,7 @@ noexcept try // The restart flag can be set by the console command "restart" which // calls ircd::quit() to clean break from the run() loop. if(ircd::restart) - ircd::syscall(::execve, _argv[0], _argv, _envp); + do_restart(_argv, _envp); return EXIT_SUCCESS; } @@ -485,6 +486,26 @@ enable_coredumps() } #endif +void +do_restart(char *const *const &_argv, + char *const *const &_envp) +{ + const auto args + { + ircd::replace(std::string(ircd::restart) + ' ', ' ', '\0') + }; + + std::vector argv{_argv[0]}; + for(size_t i(0); i < args.size(); ++i) + { + argv.emplace_back(const_cast(args.data() + i)); + for(; i < args.size() && args.at(i) != '\0'; ++i); + } + + argv.emplace_back(nullptr); + ircd::syscall(::execve, _argv[0], argv.data(), _envp); +} + /// These operations are safe to call before ircd::init() and anytime after /// static initialization. void diff --git a/include/ircd/ircd.h b/include/ircd/ircd.h index 8d72b6809..c4ed01560 100644 --- a/include/ircd/ircd.h +++ b/include/ircd/ircd.h @@ -114,8 +114,10 @@ namespace ircd // Diagnostic Mode Options extern conf::item diagnostic; + // Restart-Assist + extern conf::item restart; + // Operating Mode Selectors - extern conf::item restart; extern conf::item debugmode; extern conf::item maintenance; extern conf::item soft_assert; diff --git a/ircd/ircd.cc b/ircd/ircd.cc index 3be15db78..1f0c09f86 100644 --- a/ircd/ircd.cc +++ b/ircd/ircd.cc @@ -41,17 +41,24 @@ ircd::version_abi "IRCd", info::versions::ABI, 0, {0, 0, 0}, ircd::info::version }; -/// Courtesy indicator; this item allows the library to indicate to the -/// embedder that they should restart their application (or reload this library -/// if available). The use-case here is for features like the `restart` command -/// in the console module. Such a command triggers a normal quit and the -/// application may exit normally; therefor the embedder should check this -/// item to perform a restart rather than exiting. +/// This item allows the library to indicate to the embedder that they should +/// restart their application (or reload this library if available). The +/// use-case here is for features like the `restart` command in the console +/// module. Such a command triggers a normal quit and the application may exit +/// normally; therefor the embedder should check this item to perform a restart +/// rather than exiting. +/// +/// This item is a string to allow for different program options at restart. +/// For now this is limited to space-separated arguments without respect for +/// quoting (for now), so no arguments can have spaces. +/// +/// Empty string disables restart. The name of the executable should not be +/// prefixed to the string. decltype(ircd::restart) ircd::restart { { "name", "ircd.restart" }, - { "default", false }, + { "default", std::string{} }, { "persist", false }, }; diff --git a/modules/console.cc b/modules/console.cc index c497b6ba7..6fa28fcad 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -570,7 +570,25 @@ console_cmd__bt(opt &out, const string_view &line) bool console_cmd__restart(opt &out, const string_view &line) { - ircd::restart.set("true"); + std::string argv(line); + + size_t swargs(0), posargs(0); + ircd::tokens(line, ' ', [&swargs, &posargs] + (const auto &token) + { + swargs += startswith(token, '-'); + posargs += !startswith(token, '-'); + }); + + if(!posargs) + { + argv += swargs? " "_sv: ""_sv; + argv += m::origin(m::my()); + argv += ' '; + argv += m::server_name(m::my()); + } + + ircd::restart.set(argv); ircd::quit(); return false; }