#include "dbus-service.h"
#include "special.h"
#include "bus-errors.h"
-
-#define COMMENTS "#;\n"
-#define NEWLINES "\n\r"
+#include "exit-status.h"
+#include "def.h"
+#include "util.h"
#ifdef HAVE_SYSV_COMPAT
-#define DEFAULT_SYSV_TIMEOUT_USEC (3*USEC_PER_MINUTE)
+#define DEFAULT_SYSV_TIMEOUT_USEC (5*USEC_PER_MINUTE)
typedef enum RunlevelType {
RUNLEVEL_UP,
{ "boot.d", SPECIAL_SYSINIT_TARGET, RUNLEVEL_SYSINIT },
#endif
-#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU)
+#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU) || defined(TARGET_FRUGALWARE)
/* Debian style rcS.d */
{ "rcS.d", SPECIAL_SYSINIT_TARGET, RUNLEVEL_SYSINIT },
#endif
s->timer_watch.type = WATCH_INVALID;
#ifdef HAVE_SYSV_COMPAT
s->sysv_start_priority = -1;
+ s->sysv_start_priority_from_rcnd = -1;
#endif
s->socket_fd = -1;
+ s->guess_main_pid = true;
exec_context_init(&s->exec_context);
+ s->exec_context.std_output = u->meta.manager->default_std_output;
+ s->exec_context.std_error = u->meta.manager->default_std_error;
RATELIMIT_INIT(s->ratelimit, 10*USEC_PER_SEC, 5);
exec_context_done(&s->exec_context);
exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX);
s->control_command = NULL;
+ s->main_command = NULL;
/* This will leak a process, but at least no memory or any of
* our resources */
if (!(r = new(char, strlen(name) + sizeof(".service"))))
return NULL;
+#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU)
+ if (endswith(name, ".sh"))
+ /* Drop Debian-style .sh suffix */
+ strcpy(stpcpy(r, name) - 3, ".service");
+#endif
+#ifdef TARGET_SUSE
if (startswith(name, "boot."))
/* Drop SuSE-style boot. prefix */
strcpy(stpcpy(r, name + 5), ".service");
- else if (endswith(name, ".sh"))
- /* Drop Debian-style .sh suffix */
- strcpy(stpcpy(r, name) - 3, ".service");
-#ifdef TARGET_ARCH
- else if (startswith(name, "@"))
- /* Drop Arch-style background prefix */
- strcpy(stpcpy(r, name + 1), ".service");
+#endif
+#ifdef TARGET_FRUGALWARE
+ if (startswith(name, "rc."))
+ /* Drop Frugalware-style rc. prefix */
+ strcpy(stpcpy(r, name + 3), ".service");
#endif
else
/* Normal init scripts */
static const char * const table[] = {
/* LSB defined facilities */
"local_fs", SPECIAL_LOCAL_FS_TARGET,
+#ifndef TARGET_MANDRIVA
+ /* Due to unfortunate name selection in Mandriva,
+ * $network is provided by network-up which is ordered
+ * after network which actually starts interfaces.
+ * To break the loop, just ignore it */
"network", SPECIAL_NETWORK_TARGET,
+#endif
"named", SPECIAL_NSS_LOOKUP_TARGET,
"portmap", SPECIAL_RPCBIND_TARGET,
"remote_fs", SPECIAL_REMOTE_FS_TARGET,
"syslog", SPECIAL_SYSLOG_TARGET,
"time", SPECIAL_RTC_SET_TARGET,
- /* Debian extensions */
+ /* common extensions */
+ "mail-transfer-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
+ "x-display-manager", SPECIAL_DISPLAY_MANAGER_SERVICE,
+ "null", NULL,
+
#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU)
"mail-transport-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
#endif
- "mail-transfer-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
- "x-display-manager", SPECIAL_DISPLAY_MANAGER_SERVICE,
#ifdef TARGET_FEDORA
- /* Fedora extensions */
"MTA", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
"smtpdaemon", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
"httpd", SPECIAL_HTTP_DAEMON_TARGET,
#endif
- /* SuSE extensions */
- "null", NULL
-
+#ifdef TARGET_SUSE
+ "smtp", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
+#endif
};
unsigned i;
/* If we don't know this name, fallback heuristics to figure
* out whether something is a target or a service alias. */
- if (*name == '$')
+ if (*name == '$') {
+ if (!unit_prefix_is_valid(n))
+ return -EINVAL;
+
/* Facilities starting with $ are most likely targets */
r = unit_name_build(n, NULL, ".target");
- else if (filename && streq(name, filename))
- /* Names equalling the file name of the services are redundant */
+ } else if (filename && streq(name, filename))
+ /* Names equaling the file name of the services are redundant */
return 0;
else
/* Everything else we assume to be normal service names */
return -ENOMEM;
finish:
-
- if (_r)
- *_r = r;
+ *_r = r;
return 1;
}
/* FIXME: Maybe we should compare the name here lexicographically? */
- if (!(r = unit_add_dependency(UNIT(s), d, UNIT(t), true)) < 0)
+ if ((r = unit_add_dependency(UNIT(s), d, UNIT(t), true)) < 0)
return r;
}
* data from the LSB header. */
if (start_priority < 0 || start_priority > 99)
log_warning("[%s:%u] Start priority out of range. Ignoring.", path, line);
- else if (s->sysv_start_priority < 0)
+ else
s->sysv_start_priority = start_priority;
char_array_0(runlevels);
if (unit_name_to_type(m) == UNIT_SERVICE)
r = unit_add_name(u, m);
- else {
- r = unit_add_dependency_by_name(u, UNIT_BEFORE, m, NULL, true);
-
- if (s->sysv_enabled) {
- int k;
-
- if ((k = unit_add_dependency_by_name_inverse(u, UNIT_WANTS, m, NULL, true)) < 0)
- r = k;
- }
- }
+ else
+ /* NB: SysV targets
+ * which are provided
+ * by a service are
+ * pulled in by the
+ * services, as an
+ * indication that the
+ * generic service is
+ * now available. This
+ * is strictly
+ * one-way. The
+ * targets do NOT pull
+ * in the SysV
+ * services! */
+ r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_WANTS, m, NULL, true);
if (r < 0)
log_error("[%s:%u] Failed to add LSB Provides name %s, ignoring: %s", path, line, m, strerror(-r));
}
r = sysv_translate_facility(n, file_name_from_path(path), &m);
- free(n);
- if (r < 0)
- goto finish;
+ if (r < 0) {
+ log_error("[%s:%u] Failed to translate LSB dependency %s, ignoring: %s", path, line, n, strerror(-r));
+ free(n);
+ continue;
+ }
+
+ free(n);
if (r == 0)
continue;
s->restart = SERVICE_RESTART_NO;
s->exec_context.std_output =
(s->meta.manager->sysv_console || s->exec_context.std_input == EXEC_INPUT_TTY)
- ? EXEC_OUTPUT_TTY : EXEC_OUTPUT_NULL;
- s->exec_context.kill_mode = KILL_PROCESS_GROUP;
+ ? EXEC_OUTPUT_TTY : s->meta.manager->default_std_output;
+ s->exec_context.kill_mode = KILL_PROCESS;
/* We use the long description only if
* no short description is set. */
if (description) {
char *d;
- if (!(d = strappend("LSB: ", description))) {
+ if (!(d = strappend(s->sysv_has_lsb ? "LSB: " : "SYSV: ", description))) {
r = -ENOMEM;
goto finish;
}
u->meta.description = d;
}
+ /* The priority that has been set in /etc/rcN.d/ hierarchies
+ * takes precedence over what is stored as default in the LSB
+ * header */
+ if (s->sysv_start_priority_from_rcnd >= 0)
+ s->sysv_start_priority = s->sysv_start_priority_from_rcnd;
+
u->meta.load_state = UNIT_LOADED;
r = 0;
assert(s);
assert(name);
- /* For SysV services we strip the boot. or .sh
+ /* For SysV services we strip the boot.*, rc.* and *.sh
* prefixes/suffixes. */
- if (startswith(name, "boot.") ||
- endswith(name, ".sh.service"))
+#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU)
+ if (endswith(name, ".sh.service"))
+ return -ENOENT;
+#endif
+
+#ifdef TARGET_SUSE
+ if (startswith(name, "boot."))
return -ENOENT;
+#endif
+
+#ifdef TARGET_FRUGALWARE
+ if (startswith(name, "rc."))
+ return -ENOENT;
+#endif
STRV_FOREACH(p, s->meta.manager->lookup_paths.sysvinit_path) {
char *path;
r = service_load_sysv_path(s, path);
+#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU)
if (r >= 0 && s->meta.load_state == UNIT_STUB) {
- /* Try Debian style xxx.sh source'able init scripts */
+ /* Try Debian style *.sh source'able init scripts */
strcat(path, ".sh");
r = service_load_sysv_path(s, path);
}
-
+#endif
free(path);
+#ifdef TARGET_SUSE
if (r >= 0 && s->meta.load_state == UNIT_STUB) {
- /* Try SUSE style boot.xxx init scripts */
+ /* Try SUSE style boot.* init scripts */
if (asprintf(&path, "%s/boot.%s", *p, name) < 0)
return -ENOMEM;
+ /* Drop .service suffix */
path[strlen(path)-8] = 0;
r = service_load_sysv_path(s, path);
free(path);
}
+#endif
+
+#ifdef TARGET_FRUGALWARE
+ if (r >= 0 && s->meta.load_state == UNIT_STUB) {
+ /* Try Frugalware style rc.* init scripts */
+
+ if (asprintf(&path, "%s/rc.%s", *p, name) < 0)
+ return -ENOMEM;
+
+ /* Drop .service suffix */
+ path[strlen(path)-8] = 0;
+ r = service_load_sysv_path(s, path);
+ free(path);
+ }
+#endif
if (r < 0)
return r;
else
continue;
- if (!(r = unit_add_dependency(UNIT(s), d, UNIT(t), true)) < 0)
+ if ((r = unit_add_dependency(UNIT(s), d, UNIT(t), true)) < 0)
return r;
}
return -EINVAL;
}
+ if (s->type == SERVICE_ONESHOT &&
+ s->exec_command[SERVICE_EXEC_RELOAD]) {
+ log_error("%s has an ExecReload setting, which is not allowed for Type=oneshot services. Refusing.", s->meta.id);
+ return -EINVAL;
+ }
+
if (s->type == SERVICE_DBUS && !s->bus_name) {
log_error("%s is of type D-Bus but no D-Bus service name has been specified. Refusing.", s->meta.id);
return -EINVAL;
if ((r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_BASIC_TARGET, NULL, true)) < 0)
return r;
- } else if (s->meta.manager->running_as == MANAGER_SESSION) {
+ } else if (s->meta.manager->running_as == MANAGER_USER) {
if ((r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SOCKETS_TARGET, NULL, true)) < 0)
return r;
if ((r = unit_add_exec_dependencies(u, &s->exec_context)) < 0)
return r;
- if ((r = unit_add_default_cgroup(u)) < 0)
+ if ((r = unit_add_default_cgroups(u)) < 0)
return r;
#ifdef HAVE_SYSV_COMPAT
s->notify_access = NOTIFY_MAIN;
if (s->type == SERVICE_DBUS || s->bus_name)
- if ((r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_DBUS_TARGET, NULL, true)) < 0)
+ if ((r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true)) < 0)
return r;
if (s->meta.default_dependencies)
"%sPermissionsStartOnly: %s\n"
"%sRootDirectoryStartOnly: %s\n"
"%sRemainAfterExit: %s\n"
+ "%sGuessMainPID: %s\n"
"%sType: %s\n"
"%sRestart: %s\n"
"%sNotifyAccess: %s\n",
prefix, yes_no(s->permissions_start_only),
prefix, yes_no(s->root_directory_start_only),
prefix, yes_no(s->remain_after_exit),
+ prefix, yes_no(s->guess_main_pid),
prefix, service_type_to_string(s->type),
prefix, service_restart_to_string(s->restart),
prefix, notify_access_to_string(s->notify_access));
assert(s);
- if (s->main_pid_known)
- return 0;
-
- assert(s->main_pid <= 0);
-
if (!s->pid_file)
return -ENOENT;
assert(s);
+ /* If we know it anyway, don't ever fallback to unreliable
+ * heuristics */
if (s->main_pid_known)
return 0;
+ if (!s->guess_main_pid)
+ return 0;
+
assert(s->main_pid <= 0);
if ((pid = cgroup_bonding_search_main_pid_list(s->meta.cgroup_bondings)) <= 0)
state != SERVICE_RELOAD &&
state != SERVICE_STOP &&
state != SERVICE_STOP_SIGTERM &&
- state != SERVICE_STOP_SIGKILL)
+ state != SERVICE_STOP_SIGKILL) {
service_unwatch_main_pid(s);
+ s->main_command = NULL;
+ }
if (state != SERVICE_START_PRE &&
state != SERVICE_START &&
if (old_state != state)
log_debug("%s changed %s -> %s", s->meta.id, service_state_to_string(old_state), service_state_to_string(state));
- unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state]);
+ unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], !s->reload_failure);
+ s->reload_failure = false;
}
static int service_coldplug(Unit *u) {
}
if (set_notify_socket)
- if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=@%s", s->meta.manager->notify_socket) < 0) {
+ if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", s->meta.manager->notify_socket) < 0) {
r = -ENOMEM;
goto fail;
}
goto fail;
}
-#ifdef HAVE_SYSV_COMPAT
- /* Make sure we set TERM=linux for SysV scripts, since some
- * require it to be set from the kernel */
- if (s->sysv_path && !strv_env_get(s->meta.manager->environment, "TERM"))
- if (!(our_env[n_env++] = strdup("TERM=linux"))) {
- r = -ENOMEM;
- goto fail;
- }
-#endif
-
if (!(final_env = strv_env_merge(2,
s->meta.manager->environment,
our_env,
service_unwatch_control_pid(s);
- s->control_command_id = SERVICE_EXEC_STOP_POST;
if ((s->control_command = s->exec_command[SERVICE_EXEC_STOP_POST])) {
+ s->control_command_id = SERVICE_EXEC_STOP_POST;
+
if ((r = service_spawn(s,
s->control_command,
true,
int sig = (state == SERVICE_STOP_SIGTERM || state == SERVICE_FINAL_SIGTERM) ? s->exec_context.kill_signal : SIGKILL;
if (s->main_pid > 0) {
- if (kill(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
- -s->main_pid :
- s->main_pid, sig) < 0 && errno != ESRCH)
-
+ if (kill_and_sigcont(s->main_pid, sig) < 0 && errno != ESRCH)
log_warning("Failed to kill main process %li: %m", (long) s->main_pid);
else
wait_for_exit = true;
}
if (s->control_pid > 0) {
- if (kill(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
- -s->control_pid :
- s->control_pid, sig) < 0 && errno != ESRCH)
+ if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
else
if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
goto fail;
- if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, pid_set)) < 0) {
+ if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, true, pid_set)) < 0) {
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
log_warning("Failed to kill control group: %s", strerror(-r));
} else if (r > 0)
wait_for_exit = true;
set_free(pid_set);
+ pid_set = NULL;
}
}
service_unwatch_control_pid(s);
- s->control_command_id = SERVICE_EXEC_STOP;
if ((s->control_command = s->exec_command[SERVICE_EXEC_STOP])) {
+ s->control_command_id = SERVICE_EXEC_STOP;
+
if ((r = service_spawn(s,
s->control_command,
true,
service_unwatch_control_pid(s);
- s->control_command_id = SERVICE_EXEC_START_POST;
if ((s->control_command = s->exec_command[SERVICE_EXEC_START_POST])) {
+ s->control_command_id = SERVICE_EXEC_START_POST;
+
if ((r = service_spawn(s,
s->control_command,
true,
static void service_enter_start(Service *s) {
pid_t pid;
int r;
+ ExecCommand *c;
assert(s);
else
service_unwatch_main_pid(s);
- s->control_command_id = SERVICE_EXEC_START;
- s->control_command = s->exec_command[SERVICE_EXEC_START];
+ if (s->type == SERVICE_FORKING) {
+ s->control_command_id = SERVICE_EXEC_START;
+ c = s->control_command = s->exec_command[SERVICE_EXEC_START];
+
+ s->main_command = NULL;
+ } else {
+ s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
+ s->control_command = NULL;
+
+ c = s->main_command = s->exec_command[SERVICE_EXEC_START];
+ }
if ((r = service_spawn(s,
- s->control_command,
+ c,
s->type == SERVICE_FORKING || s->type == SERVICE_DBUS || s->type == SERVICE_NOTIFY,
true,
true,
service_unwatch_control_pid(s);
- s->control_command_id = SERVICE_EXEC_START_PRE;
if ((s->control_command = s->exec_command[SERVICE_EXEC_START_PRE])) {
+ s->control_command_id = SERVICE_EXEC_START_PRE;
+
if ((r = service_spawn(s,
s->control_command,
true,
service_unwatch_control_pid(s);
- s->control_command_id = SERVICE_EXEC_RELOAD;
if ((s->control_command = s->exec_command[SERVICE_EXEC_RELOAD])) {
+ s->control_command_id = SERVICE_EXEC_RELOAD;
+
if ((r = service_spawn(s,
s->control_command,
true,
fail:
log_warning("%s failed to run 'reload' task: %s", s->meta.id, strerror(-r));
- service_enter_stop(s, false);
+ s->reload_failure = true;
+ service_enter_running(s, true);
}
static void service_run_next_control(Service *s, bool success) {
service_enter_signal(s, SERVICE_STOP_SIGTERM, false);
else if (s->state == SERVICE_STOP_POST)
service_enter_dead(s, false, true);
- else
+ else if (s->state == SERVICE_RELOAD) {
+ s->reload_failure = true;
+ service_enter_running(s, true);
+ } else
service_enter_stop(s, false);
}
int r;
assert(s);
- assert(s->control_command);
- assert(s->control_command->command_next);
+ assert(s->main_command);
+ assert(s->main_command->command_next);
+ assert(s->type == SERVICE_ONESHOT);
if (!success)
s->failure = true;
- assert(s->control_command_id == SERVICE_EXEC_START);
- assert(s->type == SERVICE_ONESHOT);
-
- s->control_command = s->control_command->command_next;
+ s->main_command = s->main_command->command_next;
service_unwatch_main_pid(s);
if ((r = service_spawn(s,
- s->control_command,
+ s->main_command,
false,
true,
true,
return service_state_to_string(SERVICE(u)->state);
}
-#ifdef HAVE_SYSV_COMPAT
static bool service_check_gc(Unit *u) {
Service *s = SERVICE(u);
assert(s);
- return !!s->sysv_path;
-}
+ /* Never clean up services that still have a process around,
+ * even if the service is formally dead. */
+ if (cgroup_good(s) > 0 ||
+ main_pid_good(s) > 0 ||
+ control_pid_good(s) > 0)
+ return true;
+
+#ifdef HAVE_SYSV_COMPAT
+ if (s->sysv_path)
+ return true;
#endif
+ return false;
+}
+
static bool service_check_snapshot(Unit *u) {
Service *s = SERVICE(u);
s->main_pid = 0;
exec_status_exit(&s->main_exec_status, pid, code, status, s->exec_context.utmp_id);
- if (s->type != SERVICE_FORKING && s->control_command) {
- s->control_command->exec_status = s->main_exec_status;
+ /* If this is not a forking service than the main
+ * process got started and hence we copy the exit
+ * status so that it is recorded both as main and as
+ * control process exit status */
+ if (s->main_command) {
+ s->main_command->exec_status = s->main_exec_status;
- if (s->control_command->ignore)
+ if (s->main_command->ignore)
success = true;
}
"%s: main process exited, code=%s, status=%i", u->meta.id, sigchld_code_to_string(code), status);
s->failure = s->failure || !success;
- if (s->control_command &&
- s->control_command->command_next &&
+ if (s->main_command &&
+ s->main_command->command_next &&
success) {
/* There is another command to *
/* The service exited, so the service is officially
* gone. */
-
- s->control_command = NULL;
- s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
+ s->main_command = NULL;
switch (s->state) {
log_warning("%s: failed to load PID file %s: %s", s->meta.id, s->pid_file, strerror(-r));
}
- /* Fall through */
+ s->reload_failure = !success;
+ service_enter_running(s, true);
+ break;
case SERVICE_RELOAD:
- if (success)
- service_enter_running(s, true);
- else
- service_enter_stop(s, false);
+ if (success) {
+ service_load_pid_file(s);
+ service_search_main_pid(s);
+ }
+ s->reload_failure = !success;
+ service_enter_running(s, true);
break;
case SERVICE_STOP:
break;
case SERVICE_START_POST:
- case SERVICE_RELOAD:
log_warning("%s operation timed out. Stopping.", u->meta.id);
service_enter_stop(s, false);
break;
+ case SERVICE_RELOAD:
+ log_warning("%s operation timed out. Stopping.", u->meta.id);
+ s->reload_failure = true;
+ service_enter_running(s, true);
+ break;
+
case SERVICE_STOP:
log_warning("%s stopping timed out. Terminating.", u->meta.id);
service_enter_signal(s, SERVICE_STOP_SIGTERM, false);
break;
case SERVICE_STOP_SIGTERM:
- log_warning("%s stopping timed out. Killing.", u->meta.id);
- service_enter_signal(s, SERVICE_STOP_SIGKILL, false);
+ if (s->exec_context.send_sigkill) {
+ log_warning("%s stopping timed out. Killing.", u->meta.id);
+ service_enter_signal(s, SERVICE_STOP_SIGKILL, false);
+ } else {
+ log_warning("%s stopping timed out. Skipping SIGKILL.", u->meta.id);
+ service_enter_stop_post(s, false);
+ }
+
break;
case SERVICE_STOP_SIGKILL:
- /* Uh, wie sent a SIGKILL and it is still not gone?
+ /* Uh, we sent a SIGKILL and it is still not gone?
* Must be something we cannot kill, so let's just be
* weirded out and continue */
break;
case SERVICE_FINAL_SIGTERM:
- log_warning("%s stopping timed out (2). Killing.", u->meta.id);
- service_enter_signal(s, SERVICE_FINAL_SIGKILL, false);
+ if (s->exec_context.send_sigkill) {
+ log_warning("%s stopping timed out (2). Killing.", u->meta.id);
+ service_enter_signal(s, SERVICE_FINAL_SIGKILL, false);
+ } else {
+ log_warning("%s stopping timed out (2). Skipping SIGKILL. Entering failed mode.", u->meta.id);
+ service_enter_dead(s, false, true);
+ }
+
break;
case SERVICE_FINAL_SIGKILL:
Unit *service;
Iterator j;
int r;
-#ifdef TARGET_ARCH
- Unit *previous = NULL;
- char *arch_daemons = NULL;
- char *arch_daemons_stripped = NULL;
- char **arch_daemons_split = NULL;
-#endif
assert(m);
-#ifdef TARGET_ARCH
- if ((r = parse_env_file("/etc/rc.conf", NEWLINE,
- "DAEMONS", &arch_daemons,
- NULL)) < 0) {
-
- if (r != -ENOENT)
- log_warning("Failed to read /etc/rc.conf: %s", strerror(-r));
-
- } else if (arch_daemons) {
- if (!(arch_daemons_stripped = strchr(arch_daemons, '(')))
- arch_daemons_stripped = arch_daemons;
- else
- arch_daemons_stripped++; /* strip start paren */
-
- arch_daemons_stripped[strcspn(arch_daemons_stripped, ")")] = 0; /* strip end paren */
-
- if (!(arch_daemons_split = strv_split_quoted(arch_daemons_stripped))) {
- r = -ENOMEM;
- goto finish;
- }
-
- STRV_FOREACH(p, arch_daemons_split) {
-
- free(name);
- name = NULL;
-
- if (**p == '!') /* daemons prefixed with ! are disabled, so ignore them */
- continue;
-
- if (!(name = sysv_translate_name(*p))) {
- r = -ENOMEM;
- goto finish;
- }
-
- if ((r = manager_load_unit_prepare(m, name, NULL, NULL, &service)) < 0) {
- log_warning("Failed to prepare unit %s: %s", name, strerror(-r));
- continue;
- }
-
- if ((r = unit_add_two_dependencies_by_name_inverse(service, UNIT_AFTER, UNIT_WANTS, "multi-user.target", NULL, true)) < 0)
- goto finish;
-
- if (previous)
- if ((r = unit_add_dependency(service, UNIT_AFTER, previous, true)) < 0)
- goto finish;
-
- if (**p != '@') /* daemons prefixed with @ can be started in the background */
- previous = service;
- }
- }
-#endif
-
zero(runlevel_services);
STRV_FOREACH(p, m->lookup_paths.sysvrcnd_path)
if (de->d_name[0] == 'S') {
if (rcnd_table[i].type == RUNLEVEL_UP || rcnd_table[i].type == RUNLEVEL_SYSINIT) {
- SERVICE(service)->sysv_start_priority =
- MAX(a*10 + b, SERVICE(service)->sysv_start_priority);
+ SERVICE(service)->sysv_start_priority_from_rcnd =
+ MAX(a*10 + b, SERVICE(service)->sysv_start_priority_from_rcnd);
SERVICE(service)->sysv_enabled = true;
}
/* We honour K links only for halt/reboot. For the normal
* runlevels we assume the stop jobs will be implicitly added
- * by the core logic. Also, we don't really distuingish here
+ * by the core logic. Also, we don't really distinguish here
* between the runlevels 0 and 6 and just add them to the
* special shutdown target. On SUSE the boot.d/ runlevel is
* also used for shutdown, so we add links for that too to the
free(path);
free(fpath);
free(name);
-#ifdef TARGET_ARCH
- free(arch_daemons);
- free(arch_daemons_split);
-#endif
for (i = 0; i < ELEMENTSOF(rcnd_table); i++)
set_free(runlevel_services[i]);
}
if (s->control_pid > 0)
- if (kill(mode == KILL_PROCESS_GROUP ? -s->control_pid : s->control_pid, signo) < 0)
+ if (kill(s->control_pid, signo) < 0)
r = -errno;
if (s->main_pid > 0)
- if (kill(mode == KILL_PROCESS_GROUP ? -s->main_pid : s->main_pid, signo) < 0)
+ if (kill(s->main_pid, signo) < 0)
r = -errno;
if (mode == KILL_CONTROL_GROUP) {
goto finish;
}
- if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, pid_set)) < 0)
+ if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, false, pid_set)) < 0)
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
r = q;
}
.active_state = service_active_state,
.sub_state_to_string = service_sub_state_to_string,
-#ifdef HAVE_SYSV_COMPAT
.check_gc = service_check_gc,
-#endif
.check_snapshot = service_check_snapshot,
.sigchld_event = service_sigchld_event,