From: Davin McCall Date: Sat, 27 Jul 2019 10:45:29 +0000 (+1000) Subject: Implement dinitctl restart, addresses #14 X-Git-Tag: v0.7.0~16 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=0e246eadce23ae91c48a52ef10b10d61bc8bd854;p=oweals%2Fdinit.git Implement dinitctl restart, addresses #14 --- diff --git a/src/control.cc b/src/control.cc index e2e8d60..e4eb578 100644 --- a/src/control.cc +++ b/src/control.cc @@ -184,7 +184,7 @@ bool control_conn_t::check_dependents(service_record *service, bool &had_depende size_t num_depts = 0; for (service_dep *dep : service->get_dependents()) { - if (dep->dep_type == dependency_type::REGULAR) { + if (dep->dep_type == dependency_type::REGULAR && dep->holding_acq) { num_depts++; // find or allocate a service handle handle_t dept_handle = allocate_service_handle(dep->get_from()); @@ -223,7 +223,7 @@ bool control_conn_t::process_start_stop(int pktType) } // 1 byte: packet type - // 1 byte: pin in requested state (0 = no pin, 1 = pin) + // 1 byte: flags eg pin in requested state (0 = no pin, 1 = pin) // 4 bytes: service handle bool do_pin = ((rbuf[1] & 1) == 1); @@ -258,6 +258,12 @@ bool control_conn_t::process_start_stop(int pktType) { // force service to stop bool gentle = ((rbuf[1] & 2) == 2); + bool do_restart = ((rbuf[1] & 4) == 4); + bool is_active = service->is_marked_active(); + if (do_restart && services->is_shutting_down()) { + ack_buf[0] = DINIT_RP_NAK; + break; + } if (gentle) { // Check dependents; return appropriate response if any will be affected bool has_dependents; @@ -273,7 +279,13 @@ bool control_conn_t::process_start_stop(int pktType) service->stop(true); service->forced_stop(); services->process_queues(); - if (service->get_state() == service_state_t::STOPPED) ack_buf[0] = DINIT_RP_ALREADYSS; + service_state_t wanted_state = service_state_t::STOPPED; + if (do_restart) { + service->start(is_active); + wanted_state = service_state_t::STARTED; + services->process_queues(); + } + if (service->get_state() == wanted_state) ack_buf[0] = DINIT_RP_ALREADYSS; break; } case DINIT_CP_WAKESERVICE: diff --git a/src/dinitctl.cc b/src/dinitctl.cc index e810199..9404335 100644 --- a/src/dinitctl.cc +++ b/src/dinitctl.cc @@ -63,6 +63,7 @@ enum class command_t { START_SERVICE, WAKE_SERVICE, STOP_SERVICE, + RESTART_SERVICE, RELEASE_SERVICE, UNPIN_SERVICE, UNLOAD_SERVICE, @@ -132,7 +133,7 @@ int main(int argc, char **argv) } service_name = argv[i]; } - else if ((command == command_t::STOP_SERVICE) + else if ((command == command_t::STOP_SERVICE || command == command_t::RESTART_SERVICE) && (strcmp(argv[i], "--force") == 0 || strcmp(argv[i], "-f") == 0)) { do_force = true; } @@ -151,6 +152,9 @@ int main(int argc, char **argv) else if (strcmp(argv[i], "stop") == 0) { command = command_t::STOP_SERVICE; } + else if (strcmp(argv[i], "restart") == 0) { + command = command_t::RESTART_SERVICE; + } else if (strcmp(argv[i], "release") == 0) { command = command_t::RELEASE_SERVICE; } @@ -507,6 +511,7 @@ static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *serv int pcommand = 0; switch (command) { case command_t::STOP_SERVICE: + case command_t::RESTART_SERVICE: // stop, and then start pcommand = DINIT_CP_STOPSERVICE; break; case command_t::RELEASE_SERVICE: @@ -528,11 +533,16 @@ static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *serv char buf[2 + sizeof(handle)]; buf[0] = pcommand; buf[1] = (do_pin ? 1 : 0) | ((pcommand == DINIT_CP_STOPSERVICE && !do_force) ? 2 : 0); + if (command == command_t::RESTART_SERVICE) { + buf[1] |= 4; + } memcpy(buf + 2, &handle, sizeof(handle)); write_all_x(socknum, buf, 2 + sizeof(handle)); wait_for_reply(rbuffer, socknum); - if (rbuffer[0] == DINIT_RP_ALREADYSS) { + auto reply_pkt_h = rbuffer[0]; + rbuffer.consume(1); // consume header + if (reply_pkt_h == DINIT_RP_ALREADYSS) { bool already = (state == wanted_state); if (verbose) { cout << "Service " << (already ? "(already) " : "") @@ -540,11 +550,10 @@ static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *serv } return 0; // success! } - if (rbuffer[0] == DINIT_RP_DEPENDENTS && pcommand == DINIT_CP_STOPSERVICE) { + if (reply_pkt_h == DINIT_RP_DEPENDENTS && pcommand == DINIT_CP_STOPSERVICE) { cerr << "dinitctl: Cannot stop service due to the following dependents:\n" "(Only direct dependents are listed. Exercise caution before using '--force' !!)\n"; // size_t number, N * handle_t handles - rbuffer.consume(1); // packet header size_t number; rbuffer.fill_to(socknum, sizeof(number)); rbuffer.extract(&number, 0, sizeof(number)); @@ -566,11 +575,10 @@ static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *serv cerr << "\n"; return 1; } - if (rbuffer[0] != DINIT_RP_ACK) { - cerr << "dinitctl: Protocol error." << endl; + if (reply_pkt_h != DINIT_RP_ACK && reply_pkt_h != DINIT_RP_ALREADYSS) { + cerr << "dinitctl: protocol error." << endl; return 1; } - rbuffer.consume(1); } if (! wait_for_service) { diff --git a/src/includes/service.h b/src/includes/service.h index 487d976..64ad50d 100644 --- a/src/includes/service.h +++ b/src/includes/service.h @@ -459,6 +459,12 @@ class service_record return desired_state; } + // Is the service explicitly marked active? + bool is_marked_active() noexcept + { + return start_explicit; + } + // Set logfile, should be done before service is started void set_log_file(const string &logfile) {