-/*-*- Mode: C; c-basic-offset: 8 -*-*/
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
#include "dbus-unit.h"
#include "special.h"
#include "cgroup-util.h"
+#include "missing.h"
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
[UNIT_SERVICE] = &service_vtable,
if (UNIT_VTABLE(u)->no_gc)
return true;
+ if (u->meta.no_gc)
+ return true;
+
if (u->meta.job)
return true;
timestamp1[FORMAT_TIMESTAMP_MAX],
timestamp2[FORMAT_TIMESTAMP_MAX],
timestamp3[FORMAT_TIMESTAMP_MAX],
- timestamp4[FORMAT_TIMESTAMP_MAX];
+ timestamp4[FORMAT_TIMESTAMP_MAX],
+ timespan[FORMAT_TIMESPAN_MAX];
+ Unit *following;
assert(u);
assert(u->meta.type >= 0);
SET_FOREACH(t, u->meta.names, i)
fprintf(f, "%s\tName: %s\n", prefix, t);
+ if ((following = unit_following(u)))
+ fprintf(f, "%s\tFollowing: %s\n", prefix, following->meta.id);
+
if (u->meta.fragment_path)
fprintf(f, "%s\tFragment Path: %s\n", prefix, u->meta.fragment_path);
+ if (u->meta.job_timeout > 0)
+ fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->meta.job_timeout));
+
for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
Unit *other;
fprintf(f,
"%s\tRecursive Stop: %s\n"
"%s\tStopWhenUnneeded: %s\n"
- "%s\tOnlyByDependency: %s\n"
+ "%s\tRefuseManualStart: %s\n"
+ "%s\tRefuseManualStop: %s\n"
"%s\tDefaultDependencies: %s\n"
"%s\tIgnoreDependencyFailure: %s\n",
prefix, yes_no(u->meta.recursive_stop),
prefix, yes_no(u->meta.stop_when_unneeded),
- prefix, yes_no(u->meta.only_by_dependency),
+ prefix, yes_no(u->meta.refuse_manual_start),
+ prefix, yes_no(u->meta.refuse_manual_stop),
prefix, yes_no(u->meta.default_dependencies),
prefix, yes_no(u->meta.ignore_dependency_failure));
fprintf(f,
"%s\tMerged into: %s\n",
prefix, u->meta.merged_into->meta.id);
+ else if (u->meta.load_state == UNIT_FAILED)
+ fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->meta.load_error));
+
if (u->meta.job)
job_dump(u->meta.job, f, prefix2);
return 0;
}
-/* Common implementation for multiple backends */
-int unit_load_nop(Unit *u) {
- assert(u);
-
- if (u->meta.load_state == UNIT_STUB)
- u->meta.load_state = UNIT_LOADED;
-
- return 0;
-}
-
int unit_load(Unit *u) {
int r;
fail:
u->meta.load_state = UNIT_FAILED;
+ u->meta.load_error = r;
unit_add_to_dbus_queue(u);
- log_notice("Failed to load configuration for %s: %s", u->meta.id, strerror(-r));
+ log_debug("Failed to load configuration for %s: %s", u->meta.id, strerror(-r));
return r;
}
return -EBADR;
state = unit_active_state(u);
- if (unit_active_state(u) == UNIT_RELOADING)
+ if (state == UNIT_RELOADING)
return -EALREADY;
- if (unit_active_state(u) != UNIT_ACTIVE)
+ if (state != UNIT_ACTIVE)
return -ENOEXEC;
unit_add_to_dbus_queue(u);
SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTS], i)
if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
+
+ SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTED_BY], i)
+ if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
}
static void retroactively_stop_dependencies(Unit *u) {
* even if they might map to the same high-level
* UnitActiveState! That means that ns == os is OK an expected
* behaviour here. For example: if a mount point is remounted
- * this function will be called too and the utmp code below
- * relies on that! */
+ * this function will be called too! */
dual_timestamp_get(&ts);
* failed previously due to EAGAIN. */
job_add_to_run_queue(u->meta.job);
-
/* Let's check whether this state change constitutes a
* finished job, or maybe cotradicts a running job and
* hence needs to invalidate jobs. */
job_finish_and_invalidate(u->meta.job, true);
else if (u->meta.job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
unexpected = true;
- job_finish_and_invalidate(u->meta.job, false);
+
+ if (UNIT_IS_INACTIVE_OR_MAINTENANCE(ns))
+ job_finish_and_invalidate(u->meta.job, ns != UNIT_MAINTENANCE);
}
break;
job_finish_and_invalidate(u->meta.job, true);
else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) {
unexpected = true;
- job_finish_and_invalidate(u->meta.job, false);
+
+ if (UNIT_IS_INACTIVE_OR_MAINTENANCE(ns))
+ job_finish_and_invalidate(u->meta.job, ns != UNIT_MAINTENANCE);
}
}
case JOB_RESTART:
case JOB_TRY_RESTART:
- if (ns == UNIT_INACTIVE || ns == UNIT_MAINTENANCE)
+ if (UNIT_IS_INACTIVE_OR_MAINTENANCE(ns))
job_finish_and_invalidate(u->meta.job, true);
else if (u->meta.job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
unexpected = true;
/* Some names are special */
if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) {
- if (unit_has_name(u, SPECIAL_DBUS_SERVICE)) {
+ if (unit_has_name(u, SPECIAL_DBUS_SERVICE))
/* The bus just might have become available,
* hence try to connect to it, if we aren't
* yet connected. */
bus_init(u->meta.manager);
- }
if (unit_has_name(u, SPECIAL_SYSLOG_SERVICE))
/* The syslog daemon just might have become
* we aren't yet connected. */
log_open();
- if (u->meta.type == UNIT_MOUNT)
- /* Another directory became available, let's
- * check if that is enough to write our utmp
- * entry. */
- manager_write_utmp_reboot(u->meta.manager);
-
- if (u->meta.type == UNIT_TARGET)
- /* A target got activated, maybe this is a runlevel? */
- manager_write_utmp_runlevel(u->meta.manager, u);
+ if (u->meta.type == UNIT_SERVICE &&
+ !UNIT_IS_ACTIVE_OR_RELOADING(os)) {
+ /* Write audit record if we have just finished starting up */
+ manager_send_unit_audit(u->meta.manager, u, AUDIT_SERVICE_START, 1);
+ u->meta.in_audit = true;
+ }
- } else if (!UNIT_IS_ACTIVE_OR_RELOADING(ns)) {
+ } else {
if (unit_has_name(u, SPECIAL_SYSLOG_SERVICE))
/* The syslog daemon might just have
/* We don't care about D-Bus here, since we'll get an
* asynchronous notification for it anyway. */
+
+ if (u->meta.type == UNIT_SERVICE &&
+ UNIT_IS_INACTIVE_OR_MAINTENANCE(ns) &&
+ !UNIT_IS_INACTIVE_OR_MAINTENANCE(os)) {
+
+ /* Hmm, if there was no start record written
+ * write it now, so that we always have a nice
+ * pair */
+ if (!u->meta.in_audit) {
+ manager_send_unit_audit(u->meta.manager, u, AUDIT_SERVICE_START, ns == UNIT_INACTIVE);
+
+ if (ns == UNIT_INACTIVE)
+ manager_send_unit_audit(u->meta.manager, u, AUDIT_SERVICE_STOP, true);
+ } else
+ /* Write audit record if we have just finished shutting down */
+ manager_send_unit_audit(u->meta.manager, u, AUDIT_SERVICE_STOP, ns == UNIT_INACTIVE);
+
+ u->meta.in_audit = false;
+ }
}
/* Maybe we finished startup and are now ready for being
assert(u);
assert(w);
- assert(w->type == WATCH_INVALID || (w->type == WATCH_TIMER && w->data.unit == u));
+ assert(w->type == WATCH_INVALID || (w->type == WATCH_UNIT_TIMER && w->data.unit == u));
/* This will try to reuse the old timer if there is one */
- if (w->type == WATCH_TIMER) {
+ if (w->type == WATCH_UNIT_TIMER) {
+ assert(w->data.unit == u);
+ assert(w->fd >= 0);
+
ours = false;
fd = w->fd;
- } else {
+ } else if (w->type == WATCH_INVALID) {
+
ours = true;
if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
return -errno;
- }
+ } else
+ assert_not_reached("Invalid watch type");
zero(its);
goto fail;
}
+ w->type = WATCH_UNIT_TIMER;
w->fd = fd;
- w->type = WATCH_TIMER;
w->data.unit = u;
return 0;
if (w->type == WATCH_INVALID)
return;
- assert(w->type == WATCH_TIMER && w->data.unit == u);
+ assert(w->type == WATCH_UNIT_TIMER);
+ assert(w->data.unit == u);
+ assert(w->fd >= 0);
assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
close_nointr_nofail(w->fd);
[UNIT_REQUIRED_BY] = _UNIT_DEPENDENCY_INVALID,
[UNIT_REQUIRED_BY_OVERRIDABLE] = _UNIT_DEPENDENCY_INVALID,
[UNIT_WANTED_BY] = _UNIT_DEPENDENCY_INVALID,
- [UNIT_CONFLICTS] = UNIT_CONFLICTS,
+ [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY,
+ [UNIT_CONFLICTED_BY] = UNIT_CONFLICTS,
[UNIT_BEFORE] = UNIT_AFTER,
[UNIT_AFTER] = UNIT_BEFORE,
[UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID,
assert(u);
+ if (!u->meta.id)
+ return NULL;
+
if (!(e = bus_path_escape(u->meta.id)))
return NULL;
return -errno;
}
+ char_array_0(line);
l = strstrip(line);
/* End marker */
timespec_load(&st.st_mtim) != u->meta.fragment_mtime;
}
-static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
- [UNIT_SERVICE] = "service",
- [UNIT_TIMER] = "timer",
- [UNIT_SOCKET] = "socket",
- [UNIT_TARGET] = "target",
- [UNIT_DEVICE] = "device",
- [UNIT_MOUNT] = "mount",
- [UNIT_AUTOMOUNT] = "automount",
- [UNIT_SNAPSHOT] = "snapshot",
- [UNIT_SWAP] = "swap"
-};
+void unit_reset_maintenance(Unit *u) {
+ assert(u);
+
+ if (UNIT_VTABLE(u)->reset_maintenance)
+ UNIT_VTABLE(u)->reset_maintenance(u);
+}
-DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
+Unit *unit_following(Unit *u) {
+ assert(u);
+
+ if (UNIT_VTABLE(u)->following)
+ return UNIT_VTABLE(u)->following(u);
+
+ return NULL;
+}
static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
[UNIT_STUB] = "stub",
[UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
[UNIT_WANTED_BY] = "WantedBy",
[UNIT_CONFLICTS] = "Conflicts",
+ [UNIT_CONFLICTED_BY] = "ConflictedBy",
[UNIT_BEFORE] = "Before",
[UNIT_AFTER] = "After",
[UNIT_REFERENCES] = "References",