X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fmanager.c;h=c062cfb5ed3f19fb33bde2d7456843022902c960;hb=e983b76024342278a0377eae116c925f2567776e;hp=ff1c70b4845762446c80382b1051a528aa0e7962;hpb=8f6df3fa98ee74eaf5c34dddd272d2e3c10c3c27;p=elogind.git diff --git a/src/manager.c b/src/manager.c index ff1c70b48..c062cfb5e 100644 --- a/src/manager.c +++ b/src/manager.c @@ -982,7 +982,7 @@ static int transaction_verify_order_one(Manager *m, Job *j, Job *from, unsigned if (delete) { - log_warning("Breaking ordering cycle by deleting job %s/%s", k->unit->meta.id, job_type_to_string(k->type)); + log_warning("Breaking ordering cycle by deleting job %s/%s", delete->unit->meta.id, job_type_to_string(delete->type)); transaction_delete_unit(m, delete->unit); return -EAGAIN; } @@ -1182,6 +1182,7 @@ static int transaction_apply(Manager *m) { j->unit->meta.job = j; j->installed = true; + m->n_installed_jobs ++; /* We're fully installed. Now let's free data we don't * need anymore. */ @@ -1535,7 +1536,7 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove return -EPERM; } - log_debug("Trying to enqueue job %s/%s", unit->meta.id, job_type_to_string(type)); + log_debug("Trying to enqueue job %s/%s/%s", unit->meta.id, job_type_to_string(type), job_mode_to_string(mode)); if ((r = transaction_add_job_and_dependencies(m, type, unit, NULL, true, override, false, e, &ret)) < 0) { transaction_abort(m); @@ -2172,6 +2173,8 @@ int manager_loop(Manager *m) { set_free_free(m->unit_path_cache); m->unit_path_cache = NULL; + manager_check_finished(m); + /* There might still be some zombies hanging around from * before we were exec()'ed. Leat's reap them */ if ((r = manager_dispatch_sigchld(m)) < 0) @@ -2296,6 +2299,75 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { } +void manager_send_unit_plymouth(Manager *m, Unit *u) { + int fd = -1; + union sockaddr_union sa; + int n = 0; + char *message = NULL; + ssize_t r; + + /* Don't generate plymouth events if the service was already + * started and we're just deserializing */ + if (m->n_deserializing > 0) + return; + + if (m->running_as != MANAGER_SYSTEM) + return; + + if (u->meta.type != UNIT_SERVICE && + u->meta.type != UNIT_MOUNT && + u->meta.type != UNIT_SWAP) + return; + + /* We set SOCK_NONBLOCK here so that we rather drop the + * message then wait for plymouth */ + if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) { + log_error("socket() failed: %m"); + return; + } + + zero(sa); + sa.sa.sa_family = AF_UNIX; + strncpy(sa.un.sun_path+1, "/ply-boot-protocol", sizeof(sa.un.sun_path)-1); + if (connect(fd, &sa.sa, sizeof(sa.un)) < 0) { + + if (errno != EPIPE && + errno != EAGAIN && + errno != ENOENT && + errno != ECONNREFUSED && + errno != ECONNRESET && + errno != ECONNABORTED) + log_error("connect() failed: %m"); + + goto finish; + } + + if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->meta.id) + 1), u->meta.id, &n) < 0) { + log_error("Out of memory"); + goto finish; + } + + errno = 0; + if ((r = write(fd, message, n + 1)) != n + 1) { + + if (errno != EPIPE && + errno != EAGAIN && + errno != ENOENT && + errno != ECONNREFUSED && + errno != ECONNRESET && + errno != ECONNABORTED) + log_error("Failed to write Plymouth message: %m"); + + goto finish; + } + +finish: + if (fd >= 0) + close_nointr_nofail(fd); + + free(message); +} + void manager_dispatch_bus_name_owner_changed( Manager *m, const char *name, @@ -2591,17 +2663,38 @@ bool manager_unit_pending_inactive(Manager *m, const char *name) { assert(name); /* Returns true if the unit is inactive or going down */ - if (!(u = manager_get_unit(m, name))) return true; - if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))) - return true; + return unit_pending_inactive(u); +} - if (u->meta.job && u->meta.job->type == JOB_STOP) - return true; +void manager_check_finished(Manager *m) { + char userspace[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX]; + + assert(m); + + if (dual_timestamp_is_set(&m->finish_timestamp)) + return; + + if (hashmap_size(m->jobs) > 0) + return; + + dual_timestamp_get(&m->finish_timestamp); + + if (m->running_as == MANAGER_SYSTEM) + log_info("Startup finished in %s (kernel) + %s (userspace) = %s.", + format_timespan(kernel, sizeof(kernel), + m->startup_timestamp.monotonic), + format_timespan(userspace, sizeof(userspace), + m->finish_timestamp.monotonic - m->startup_timestamp.monotonic), + format_timespan(sum, sizeof(sum), + m->finish_timestamp.monotonic)); + else + log_debug("Startup finished in %s.", + format_timespan(userspace, sizeof(userspace), + m->finish_timestamp.monotonic - m->startup_timestamp.monotonic)); - return false; } static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = {