X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fmanager.c;h=09b2c789ed0c5de538f35ef07cd46a9fa61d366d;hp=25eb4e70bef568490018b294a2297bd1361d958e;hb=cc8a7a6129145dc485c82549edd39bcb9b52fd45;hpb=4927fcae48de061393b3ce9c12d49f80d73fbf1d diff --git a/src/manager.c b/src/manager.c index 25eb4e70b..09b2c789e 100644 --- a/src/manager.c +++ b/src/manager.c @@ -1,4 +1,4 @@ -/*-*- Mode: C; c-basic-offset: 8 -*-*/ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ /*** This file is part of systemd. @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -37,7 +36,10 @@ #include #include #include + +#ifdef HAVE_AUDIT #include +#endif #include "manager.h" #include "hashmap.h" @@ -48,7 +50,6 @@ #include "ratelimit.h" #include "cgroup.h" #include "mount-setup.h" -#include "utmp-wtmp.h" #include "unit-name.h" #include "dbus-unit.h" #include "dbus-job.h" @@ -56,6 +57,7 @@ #include "path-lookup.h" #include "special.h" #include "bus-errors.h" +#include "exit-status.h" /* As soon as 16 units are in our GC queue, make sure to run a gc sweep */ #define GC_QUEUE_ENTRIES_MAX 16 @@ -250,8 +252,10 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) { if ((r = bus_init(m)) < 0) goto fail; +#ifdef HAVE_AUDIT if ((m->audit_fd = audit_open()) < 0) log_error("Failed to connect to audit log: %m"); +#endif *_m = m; return 0; @@ -788,7 +792,8 @@ static int delete_one_unmergeable_job(Manager *m, Job *j) { d = j; else d = k; - } + } else + d = j; } else if (!j->matters_to_anchor) d = j; @@ -821,7 +826,7 @@ static int transaction_merge_jobs(Manager *m, DBusError *e) { t = j->type; LIST_FOREACH(transaction, k, j->transaction_next) { - if ((r = job_type_merge(&t, k->type)) >= 0) + if (job_type_merge(&t, k->type) >= 0) continue; /* OK, we could not merge all jobs for this @@ -1290,7 +1295,6 @@ rollback: static Job* transaction_add_one_job(Manager *m, JobType type, Unit *unit, bool override, bool *is_new) { Job *j, *f; - int r; assert(m); assert(unit); @@ -1323,7 +1327,7 @@ static Job* transaction_add_one_job(Manager *m, JobType type, Unit *unit, bool o LIST_PREPEND(Job, transaction, f, j); - if ((r = hashmap_replace(m->transaction_jobs, unit, f)) < 0) { + if (hashmap_replace(m->transaction_jobs, unit, f) < 0) { job_free(j); return NULL; } @@ -1389,9 +1393,15 @@ static int transaction_add_job_and_dependencies( assert(type < _JOB_TYPE_MAX); assert(unit); - if (type != JOB_STOP && - unit->meta.load_state != UNIT_LOADED) { - dbus_set_error(e, BUS_ERROR_LOAD_FAILED, "Unit %s failed to load. See logs for details.", unit->meta.id); + if (unit->meta.load_state != UNIT_LOADED && unit->meta.load_state != UNIT_FAILED) { + dbus_set_error(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->meta.id); + return -EINVAL; + } + + if (type != JOB_STOP && unit->meta.load_state == UNIT_FAILED) { + dbus_set_error(e, BUS_ERROR_LOAD_FAILED, "Unit %s failed to load: %s. You might find more information in the logs.", + unit->meta.id, + strerror(-unit->meta.load_error)); return -EINVAL; } @@ -1777,7 +1787,7 @@ static int manager_process_notify_fd(Manager *m) { if (n >= 0) return -EIO; - if (errno == EAGAIN) + if (errno == EAGAIN || errno == EINTR) break; return -errno; @@ -1876,7 +1886,9 @@ static int manager_dispatch_sigchld(Manager *m) { (long unsigned) si.si_pid, sigchld_code_to_string(si.si_code), si.si_status, - strna(si.si_code == CLD_EXITED ? exit_status_to_string(si.si_status) : signal_to_string(si.si_status))); + strna(si.si_code == CLD_EXITED + ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL) + : signal_to_string(si.si_status))); if (!u) continue; @@ -1919,7 +1931,7 @@ static int manager_process_signal_fd(Manager *m) { if (n >= 0) return -EIO; - if (errno == EAGAIN) + if (errno == EINTR || errno == EAGAIN) break; return -errno; @@ -2251,6 +2263,11 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { if (m->audit_fd < 0) return; + /* Don't generate audit events if the service was already + * started and we're just deserializing */ + if (m->n_deserializing > 0) + return; + if (!(p = unit_name_to_prefix_and_instance(u->meta.id))) { log_error("Failed to allocate unit name for audit message: %s", strerror(ENOMEM)); return; @@ -2348,6 +2365,10 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds) { assert(f); assert(fds); + fprintf(f, "startup-timestamp=%llu %llu\n\n", + (unsigned long long) m->startup_timestamp.realtime, + (unsigned long long) m->startup_timestamp.monotonic); + HASHMAP_FOREACH_KEY(u, t, m->units, i) { if (u->meta.id != t) continue; @@ -2379,6 +2400,37 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { m->n_deserializing ++; + for (;;) { + char line[1024], *l; + + if (!fgets(line, sizeof(line), f)) { + if (feof(f)) + r = 0; + else + r = -errno; + + goto finish; + } + + char_array_0(line); + l = strstrip(line); + + if (l[0] == 0) + break; + + if (startswith(l, "startup-timestamp=")) { + unsigned long long a, b; + + if (sscanf(l+18, "%lli %llu", &a, &b) != 2) + log_debug("Failed to parse startup timestamp value %s", l+18); + else { + m->startup_timestamp.realtime = a; + m->startup_timestamp.monotonic = b; + } + } else + log_debug("Unknown serialization item '%s'", l); + } + for (;;) { Unit *u; char name[UNIT_NAME_MAX+2]; @@ -2386,9 +2438,10 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { /* Start marker */ if (!fgets(name, sizeof(name), f)) { if (feof(f)) - break; + r = 0; + else + r = -errno; - r = -errno; goto finish; } @@ -2401,14 +2454,12 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { goto finish; } +finish: if (ferror(f)) { r = -EIO; goto finish; } - r = 0; - -finish: assert(m->n_deserializing > 0); m->n_deserializing --;