-/*-*- Mode: C; c-basic-offset: 8 -*-*/
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
#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
if (!(m->notify_socket = strdup(sa.un.sun_path+1)))
return -ENOMEM;
+ log_debug("Using notification socket %s", m->notify_socket);
+
return 0;
}
#endif
free(m->notify_socket);
+ free(m->console);
lookup_paths_free(&m->lookup_paths);
strv_free(m->environment);
d = j;
else
d = k;
- }
+ } else
+ d = j;
} else if (!j->matters_to_anchor)
d = j;
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
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;
}
log_error("Unable to break cycle");
- dbus_set_error(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, "Transaction order is cyclic. See logs for details.");
+ dbus_set_error(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, "Transaction order is cyclic. See system logs for details.");
return -ENOEXEC;
}
/* Second step: Try not to stop any running services if
* we don't have to. Don't try to reverse running
* jobs if we don't have to. */
- transaction_minimize_impact(m);
+ if (mode != JOB_ISOLATE)
+ transaction_minimize_impact(m);
/* Third step: Drop redundant jobs */
transaction_drop_redundant(m);
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);
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;
}
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_ERROR) {
+ 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_ERROR) {
+ dbus_set_error(e, BUS_ERROR_LOAD_FAILED, "Unit %s failed to load: %s. You might find more information in the system logs.",
+ unit->meta.id,
+ strerror(-unit->meta.load_error));
return -EINVAL;
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, !override, override, false, e, NULL)) < 0 && r != -EBADR) {
log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
- dbus_error_free(e);
+
+ if (e)
+ dbus_error_free(e);
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_WANTS], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, false, false, false, e, NULL)) < 0) {
log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
- dbus_error_free(e);
+
+ if (e)
+ dbus_error_free(e);
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUISITE], i)
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUISITE_OVERRIDABLE], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, !override, override, false, e, NULL)) < 0 && r != -EBADR) {
log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
- dbus_error_free(e);
+
+ if (e)
+ dbus_error_free(e);
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_CONFLICTS], i)
continue;
/* No need to stop inactive jobs */
- if (UNIT_IS_INACTIVE_OR_MAINTENANCE(unit_active_state(u)))
+ if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
continue;
/* Is there already something listed for this? */
return -EINVAL;
}
+ if (mode == JOB_ISOLATE && !unit->meta.allow_isolate) {
+ dbus_set_error(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
+ return -EPERM;
+ }
+
log_debug("Trying to enqueue job %s/%s", unit->meta.id, job_type_to_string(type));
if ((r = transaction_add_job_and_dependencies(m, type, unit, NULL, true, override, false, e, &ret)) < 0) {
if (n >= 0)
return -EIO;
- if (errno == EAGAIN)
+ if (errno == EAGAIN || errno == EINTR)
break;
return -errno;
(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;
if (n >= 0)
return -EIO;
- if (errno == EAGAIN)
+ if (errno == EINTR || errno == EAGAIN)
break;
return -errno;
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;
return false;
}
-void manager_reset_maintenance(Manager *m) {
+void manager_reset_failed(Manager *m) {
Unit *u;
Iterator i;
assert(m);
HASHMAP_FOREACH(u, m->units, i)
- unit_reset_maintenance(u);
+ unit_reset_failed(u);
+}
+
+int manager_set_console(Manager *m, const char *console) {
+ char *c;
+
+ assert(m);
+
+ if (!(c = strdup(console)))
+ return -ENOMEM;
+
+ free(m->console);
+ m->console = c;
+
+ log_debug("Using kernel console %s", c);
+
+ return 0;
+}
+
+bool manager_unit_pending_inactive(Manager *m, const char *name) {
+ Unit *u;
+
+ assert(m);
+ assert(name);
+
+ /* Returns true if the unit is inactive or going down */
+ if (!(u = manager_get_unit(m, name)))
+ return true;
+
+ return unit_pending_inactive(u);
}
static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = {