A "gentle" stop won't stop if dependents will be affected, i.e. it warns
and aborts. The `--force' option (or `-f') can be used to force the
service to stop, which will also cause the dependents to stop.
Also sneak in a bug fix where certain options were not recognised.
Pin the service in the requested state. The service will not leave the state until it is unpinned, although
start/stop commands will be "remembered" while the service is pinned.
.TP
Pin the service in the requested state. The service will not leave the state until it is unpinned, although
start/stop commands will be "remembered" while the service is pinned.
.TP
+\fB\-\-force\fR
+Stop the service even if it will require stopping other services which depend on the specified service.
+.TP
\fIservice-name\fR
Specifies the name of the service to which the command applies.
.TP
\fIservice-name\fR
Specifies the name of the service to which the command applies.
.TP
static int issue_load_service(int socknum, const char *service_name, bool find_only = false);
static int check_load_reply(int socknum, cpbuffer_t &, handle_t *handle_p, service_state_t *state_p);
static int start_stop_service(int socknum, cpbuffer_t &, const char *service_name, command_t command,
static int issue_load_service(int socknum, const char *service_name, bool find_only = false);
static int check_load_reply(int socknum, cpbuffer_t &, handle_t *handle_p, service_state_t *state_p);
static int start_stop_service(int socknum, cpbuffer_t &, const char *service_name, command_t command,
- bool do_pin, bool wait_for_service, bool verbose);
+ 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 list_services(int socknum, cpbuffer_t &);
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 list_services(int socknum, cpbuffer_t &);
bool sys_dinit = false; // communicate with system daemon
bool wait_for_service = true;
bool do_pin = false;
bool sys_dinit = false; // communicate with system daemon
bool wait_for_service = true;
bool do_pin = false;
command_t command = command_t::NONE;
command_t command = command_t::NONE;
else if (strcmp(argv[i], "--pin") == 0) {
do_pin = true;
}
else if (strcmp(argv[i], "--pin") == 0) {
do_pin = true;
}
- else if (strcmp(argv[i], "--socket-path") || strcmp(argv[i], "-p")) {
+ else if (strcmp(argv[i], "--socket-path") == 0 || strcmp(argv[i], "-p") == 0) {
++i;
if (i == argc) {
cerr << "dinitctl: --socket-path/-p should be followed by socket path" << std::endl;
++i;
if (i == argc) {
cerr << "dinitctl: --socket-path/-p should be followed by socket path" << std::endl;
}
service_name = argv[i];
}
}
service_name = argv[i];
}
+ else if ((command == command_t::STOP_SERVICE)
+ && (strcmp(argv[i], "--force") == 0 || strcmp(argv[i], "-f") == 0)) {
+ do_force = true;
+ }
- cerr << "dinitctl: unrecognized option: " << argv[i] << " (use --help for help)\n";
+ cerr << "dinitctl: unrecognized/invalid option: " << argv[i] << " (use --help for help)\n";
"Note: An activated service continues running when its dependents stop.\n"
"\n"
"General options:\n"
"Note: An activated service continues running when its dependents stop.\n"
"\n"
"General options:\n"
+ " --help : show this help\n"
" -s, --system : control system daemon instead of user daemon\n"
" --quiet : suppress output (except errors)\n"
" --socket-path <path>, -p <path>\n"
" : specify socket for communication with daemon\n"
"\n"
"Command options:\n"
" -s, --system : control system daemon instead of user daemon\n"
" --quiet : suppress output (except errors)\n"
" --socket-path <path>, -p <path>\n"
" : specify socket for communication with daemon\n"
"\n"
"Command options:\n"
- " --help : show this help\n"
" --no-wait : don't wait for service startup/shutdown to complete\n"
" --no-wait : don't wait for service startup/shutdown to complete\n"
- " --pin : pin the service in the requested state\n";
+ " --pin : pin the service in the requested state\n"
+ " --force : force stop even if dependents will be affected\n";
command == command_t::ENABLE_SERVICE);
}
else {
command == command_t::ENABLE_SERVICE);
}
else {
- return start_stop_service(socknum, rbuffer, service_name, command, do_pin,
+ return start_stop_service(socknum, rbuffer, service_name, command, do_pin, do_force,
wait_for_service, verbose);
}
}
wait_for_service, verbose);
}
}
// Start/stop a service
static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *service_name,
// Start/stop a service
static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *service_name,
- command_t command, bool do_pin, bool wait_for_service, bool verbose)
+ command_t command, bool do_pin, bool do_force, bool wait_for_service, bool verbose)
{
char buf[2 + sizeof(handle)];
buf[0] = pcommand;
{
char buf[2 + sizeof(handle)];
buf[0] = pcommand;
- buf[1] = do_pin ? 1 : 0;
+ buf[1] = (do_pin ? 1 : 0) | ((pcommand == DINIT_CP_STOPSERVICE && !do_force) ? 2 : 0);
memcpy(buf + 2, &handle, sizeof(handle));
write_all_x(socknum, buf, 2 + sizeof(handle));
memcpy(buf + 2, &handle, sizeof(handle));
write_all_x(socknum, buf, 2 + sizeof(handle));
}
return 0; // success!
}
}
return 0; // success!
}
+ if (rbuffer[0] == DINIT_RP_DEPENDENTS && pcommand == DINIT_CP_STOPSERVICE) {
+ cerr << "dinitctl: Cannot stop service due to dependents (consider using --force)." << endl;
+ return 1;
+ }
if (rbuffer[0] != DINIT_RP_ACK) {
cerr << "dinitctl: Protocol error." << endl;
return 1;
if (rbuffer[0] != DINIT_RP_ACK) {
cerr << "dinitctl: Protocol error." << endl;
return 1;