From bb21b8bb1da43a892b36cb2b9eaaf5e75201ad0a Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Sun, 1 Dec 2019 14:46:27 +1000 Subject: [PATCH] Implement reload command for dinitctl --- doc/manpages/dinitctl.8.m4 | 12 +++++++++ src/dinitctl.cc | 54 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/doc/manpages/dinitctl.8.m4 b/doc/manpages/dinitctl.8.m4 index 14714ca..f627187 100644 --- a/doc/manpages/dinitctl.8.m4 +++ b/doc/manpages/dinitctl.8.m4 @@ -27,6 +27,9 @@ dinitctl \- control services supervised by Dinit [\fIoptions\fR] \fBunload\fR \fIservice-name\fR .br .B dinitctl +[\fIoptions\fR] \fBreload\fR \fIservice-name\fR +.br +.B dinitctl [\fIoptions\fR] \fBlist\fR .br .B dinitctl @@ -128,6 +131,15 @@ any pending start/stop commands will be carried out. Completely unload a service. This can only be done if the service is stopped and has no loaded dependents (i.e. dependents must be unloaded before their dependencies). .TP +\fBreload\fR +Attempt to reload a service description. This is intended as a convenience for making simple changes to a +service, without having to stop, remove dependencies to and unload the service. However it is not completely +equivalent to doing a proper unload/reload; some altered settings may not take effect until the service is +restarted, and some cannot be changed at all while the service is running. + +In particular, the type of a running service cannot be changed; nor can the \fBinittab-id\fR, \fBinittab-line\fR, +or \fBpid-file\fR settings, or the \fBruns-on-console\fR or \fBshares-console\fR flags. +.TP \fBlist\fR List loaded services and their state. Before each service, one of the following state indicators is displayed: diff --git a/src/dinitctl.cc b/src/dinitctl.cc index 03b2cd1..b2af20b 100644 --- a/src/dinitctl.cc +++ b/src/dinitctl.cc @@ -41,6 +41,7 @@ static int start_stop_service(int socknum, cpbuffer_t &, const char *service_nam bool do_pin, bool do_force, bool wait_for_service, bool verbose); static int unpin_service(int socknum, cpbuffer_t &, const char *service_name, bool verbose); static int unload_service(int socknum, cpbuffer_t &, const char *service_name); +static int reload_service(int socknum, cpbuffer_t &, const char *service_name); static int list_services(int socknum, cpbuffer_t &); static int shutdown_dinit(int soclknum, cpbuffer_t &); static int add_remove_dependency(int socknum, cpbuffer_t &rbuffer, bool add, const char *service_from, @@ -67,6 +68,7 @@ enum class command_t { RELEASE_SERVICE, UNPIN_SERVICE, UNLOAD_SERVICE, + RELOAD_SERVICE, LIST_SERVICES, SHUTDOWN, ADD_DEPENDENCY, @@ -167,6 +169,9 @@ int main(int argc, char **argv) else if (strcmp(argv[i], "unload") == 0) { command = command_t::UNLOAD_SERVICE; } + else if (strcmp(argv[i], "reload") == 0) { + command = command_t::RELOAD_SERVICE; + } else if (strcmp(argv[i], "list") == 0) { command = command_t::LIST_SERVICES; } @@ -267,6 +272,7 @@ int main(int argc, char **argv) " dinitctl [options] release [options] \n" " dinitctl [options] unpin \n" " dinitctl [options] unload \n" + " dinitctl [options] reload \n" " dinitctl [options] list\n" " dinitctl [options] shutdown\n" " dinitctl [options] add-dep \n" @@ -354,6 +360,9 @@ int main(int argc, char **argv) else if (command == command_t::UNLOAD_SERVICE) { return unload_service(socknum, rbuffer, service_name); } + else if (command == command_t::RELOAD_SERVICE) { + return reload_service(socknum, rbuffer, service_name); + } else if (command == command_t::LIST_SERVICES) { return list_services(socknum, rbuffer); } @@ -793,6 +802,51 @@ static int unload_service(int socknum, cpbuffer_t &rbuffer, const char *service_ return 0; } +static int reload_service(int socknum, cpbuffer_t &rbuffer, const char *service_name) +{ + using namespace std; + + if (issue_load_service(socknum, service_name, true) == 1) { + return 1; + } + + wait_for_reply(rbuffer, socknum); + + handle_t handle; + + if (rbuffer[0] == DINIT_RP_NOSERVICE) { + cerr << "dinitctl: service not loaded." << endl; + return 1; + } + + if (check_load_reply(socknum, rbuffer, &handle, nullptr) != 0) { + return 1; + } + + // Issue RELOAD command. + { + auto m = membuf() + .append(DINIT_CP_RELOADSERVICE) + .append(handle); + write_all_x(socknum, m); + + wait_for_reply(rbuffer, socknum); + if (rbuffer[0] == DINIT_RP_NAK) { + cerr << "dinitctl: Could not reload service; service in wrong state, incompatible change, " + "or bad service description." << endl; + return 1; + } + if (rbuffer[0] != DINIT_RP_ACK) { + cerr << "dinitctl: Protocol error." << endl; + return 1; + } + rbuffer.consume(1); + } + + cout << "Service reloaded." << endl; + return 0; +} + static int list_services(int socknum, cpbuffer_t &rbuffer) { using namespace std; -- 2.25.1