{ "RecursiveStop", config_parse_bool, &u->meta.recursive_stop, "Unit" },
{ "StopWhenUnneeded", config_parse_bool, &u->meta.stop_when_unneeded, "Unit" },
{ "OnlyByDependency", config_parse_bool, &u->meta.only_by_dependency, "Unit" },
+ { "DefaultDependencies", config_parse_bool, &u->meta.default_dependencies, "Unit" },
{ "PIDFile", config_parse_path, &u->service.pid_file, "Service" },
{ "ExecStartPre", config_parse_exec, u->service.exec_command+SERVICE_EXEC_START_PRE, "Service" },
#include "unit-name.h"
#include "path.h"
#include "dbus-path.h"
+#include "special.h"
static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
[PATH_DEAD] = UNIT_INACTIVE,
if ((r = path_add_mount_links(p)) < 0)
return r;
+
+ /* Path units shouldn't stay around on shutdown */
+ if (p->meta.default_dependencies)
+ if ((r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true)) < 0)
+ return r;
}
return path_verify(p);
if ((r = sysv_exec_commands(s)) < 0)
goto finish;
- if (!s->sysv_runlevels || chars_intersect(RUNLEVELS_UP, s->sysv_runlevels)) {
+ if (s->sysv_runlevels && !chars_intersect(RUNLEVELS_UP, s->sysv_runlevels)) {
/* If there a runlevels configured for this service
* but none of the standard ones, then we assume this
* is some special kind of service (which might be
* needed for early boot) and don't create any links
* to it. */
- if ((r = unit_add_dependency_by_name(u, UNIT_REQUIRES, SPECIAL_BASIC_TARGET, NULL, true)) < 0 ||
- (r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_BASIC_TARGET, NULL, true)) < 0)
- goto finish;
+ s->meta.default_dependencies = false;
- } else
/* Don't timeout special services during boot (like fsck) */
s->timeout_usec = 0;
+ }
/* Special setting for all SysV services */
s->type = SERVICE_FORKING;
return 0;
}
+static int service_add_default_dependencies(Service *s) {
+ int r;
+
+ assert(s);
+
+ /* Add a number of automatic dependencies useful for the
+ * majority of services. */
+
+ /* First, pull in base system */
+ if (s->meta.manager->running_as == MANAGER_SYSTEM) {
+
+ 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) {
+
+ if ((r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SOCKETS_TARGET, NULL, true)) < 0)
+ return r;
+ }
+
+ /* Second, activate normal shutdown */
+ return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
+}
+
static int service_load(Unit *u) {
int r;
Service *s = SERVICE(u);
return r;
if ((r = unit_watch_bus_name(u, s->bus_name)) < 0)
- return r;
+ return r;
}
if (s->type == SERVICE_NOTIFY && s->notify_access == NOTIFY_NONE)
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)
+ return r;
+
+ if (s->meta.default_dependencies)
+ if ((r = service_add_default_dependencies(s)) < 0)
+ return r;
}
return service_verify(s);
#include "unit-name.h"
#include "dbus-socket.h"
#include "missing.h"
+#include "special.h"
static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
[SOCKET_DEAD] = UNIT_INACTIVE,
return r;
}
+static int socket_add_default_dependencies(Socket *s) {
+ int r;
+ assert(s);
+
+ if (s->meta.manager->running_as == MANAGER_SYSTEM)
+ if ((r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true)) < 0)
+ return r;
+
+ return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
+}
+
static int socket_load(Unit *u) {
Socket *s = SOCKET(u);
int r;
if ((r = unit_add_default_cgroup(u)) < 0)
return r;
+
+ if (s->meta.default_dependencies)
+ if ((r = socket_add_default_dependencies(s)) < 0)
+ return r;
}
return socket_verify(s);
#define SPECIAL_RTC_SET_TARGET "rtc-set.target" /* LSB's $time */
#define SPECIAL_DISPLAY_MANAGER_SERVICE "display-manager.service" /* Debian's $x-display-manager */
#define SPECIAL_MAIL_TRANSFER_AGENT_TARGET "mail-transfer-agent.target" /* Debian's $mail-{transport|transfer-agent */
+#define SPECIAL_DBUS_TARGET "dbus.target"
#define SPECIAL_BASIC_TARGET "basic.target"
+#define SPECIAL_SOCKETS_TARGET "sockets.target"
#define SPECIAL_SYSINIT_TARGET "sysinit.target"
#define SPECIAL_RESCUE_TARGET "rescue.target"
#define SPECIAL_EXIT_SERVICE "exit.service"
unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state]);
}
+static int target_add_default_dependencies(Target *t) {
+ Iterator i;
+ Unit *other;
+ int r;
+
+ /* Imply ordering for requirement dependencies
+ * on target units. */
+
+ SET_FOREACH(other, t->meta.dependencies[UNIT_REQUIRES], i)
+ if ((r = unit_add_dependency(UNIT(t), UNIT_AFTER, other, true)) < 0)
+ return r;
+ SET_FOREACH(other, t->meta.dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
+ if ((r = unit_add_dependency(UNIT(t), UNIT_AFTER, other, true)) < 0)
+ return r;
+ SET_FOREACH(other, t->meta.dependencies[UNIT_WANTS], i)
+ if ((r = unit_add_dependency(UNIT(t), UNIT_AFTER, other, true)) < 0)
+ return r;
+
+ return 0;
+}
+
+static int target_load(Unit *u) {
+ Target *t = TARGET(u);
+ int r;
+
+ assert(t);
+
+ if ((r = unit_load_fragment_and_dropin(u)) < 0)
+ return r;
+
+ /* This is a new unit? Then let's add in some extras */
+ if (u->meta.load_state == UNIT_LOADED) {
+ if (u->meta.default_dependencies)
+ if ((r = target_add_default_dependencies(t)) < 0)
+ return r;
+ }
+
+ return 0;
+}
+
static int target_coldplug(Unit *u) {
Target *t = TARGET(u);
const UnitVTable target_vtable = {
.suffix = ".target",
- .load = unit_load_fragment_and_dropin,
+ .load = target_load,
.coldplug = target_coldplug,
.dump = target_dump,
#include "unit-name.h"
#include "timer.h"
#include "dbus-timer.h"
+#include "special.h"
static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
[TIMER_DEAD] = UNIT_INACTIVE,
if ((r = unit_add_dependency(u, UNIT_BEFORE, t->unit, true)) < 0)
return r;
+
+ /* Timers shouldn't stay around on shutdown */
+ if (t->meta.default_dependencies)
+ if ((r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true)) < 0)
+ return r;
}
return timer_verify(t);
u->meta.manager = m;
u->meta.type = _UNIT_TYPE_INVALID;
u->meta.deserialized_job = _JOB_TYPE_INVALID;
+ u->meta.default_dependencies = true;
return u;
}
"%s\tActive Enter Timestamp: %s\n"
"%s\tActive Exit Timestamp: %s\n"
"%s\tInactive Enter Timestamp: %s\n"
- "%s\tGC Check Good: %s\n"
- "%s\tOnly By Dependency: %s\n",
+ "%s\tGC Check Good: %s\n",
prefix, u->meta.id,
prefix, unit_description(u),
prefix, strna(u->meta.instance),
prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->meta.active_enter_timestamp.realtime)),
prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->meta.active_exit_timestamp.realtime)),
prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->meta.inactive_enter_timestamp.realtime)),
- prefix, yes_no(unit_check_gc(u)),
- prefix, yes_no(u->meta.only_by_dependency));
+ prefix, yes_no(unit_check_gc(u)));
SET_FOREACH(t, u->meta.names, i)
fprintf(f, "%s\tName: %s\n", prefix, t);
if (u->meta.load_state == UNIT_LOADED) {
fprintf(f,
"%s\tRecursive Stop: %s\n"
- "%s\tStop When Unneeded: %s\n",
+ "%s\tStopWhenUnneeded: %s\n"
+ "%s\tOnlyByDependency: %s\n"
+ "%s\tDefaultDependencies: %s\n",
prefix, yes_no(u->meta.recursive_stop),
- prefix, yes_no(u->meta.stop_when_unneeded));
+ prefix, yes_no(u->meta.stop_when_unneeded),
+ prefix, yes_no(u->meta.only_by_dependency),
+ prefix, yes_no(u->meta.default_dependencies));
LIST_FOREACH(by_unit, b, u->meta.cgroup_bondings)
fprintf(f, "%s\tControlGroup: %s:%s\n",
UnitLoadState load_state;
Unit *merged_into;
- /* Refuse manual starting, allow starting only indirectly via dependency. */
- bool only_by_dependency;
-
char *id; /* One name is special because we use it for identification. Points to an entry in the names set */
char *instance;
/* Garbage collect us we nobody wants or requires us anymore */
bool stop_when_unneeded;
+ /* Refuse manual starting, allow starting only indirectly via dependency. */
+ bool only_by_dependency;
+
+ /* Create default depedencies */
+ bool default_dependencies;
+
/* When deserializing, temporarily store the job type for this
* unit here, if there was a job scheduled */
int deserialized_job; /* This is actually of type JobType */