if (c->std_output != EXEC_OUTPUT_KMSG &&
c->std_output != EXEC_OUTPUT_SYSLOG &&
+ c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
+ c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
c->std_error != EXEC_OUTPUT_KMSG &&
- c->std_error != EXEC_OUTPUT_SYSLOG)
+ c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
+ c->std_error != EXEC_OUTPUT_KMSG &&
+ c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
return 0;
/* If syslog or kernel logging is requested, make sure our own
if (target->meta.type != UNIT_TARGET)
return 0;
- /* Only add the dependency if boths units are loaded, so that
+ /* Only add the dependency if both units are loaded, so that
* that loop check below is reliable */
if (u->meta.load_state != UNIT_LOADED ||
target->meta.load_state != UNIT_LOADED)
return 0;
+ /* If either side wants no automatic dependencies, then let's
+ * skip this */
+ if (!u->meta.default_dependencies ||
+ target->meta.default_dependencies)
+ return 0;
+
/* Don't create loops */
if (set_get(target->meta.dependencies[UNIT_BEFORE], u))
return 0;
}
static int unit_add_default_dependencies(Unit *u) {
+ static const UnitDependency deps[] = {
+ UNIT_REQUIRED_BY,
+ UNIT_REQUIRED_BY_OVERRIDABLE,
+ UNIT_WANTED_BY,
+ UNIT_BOUND_BY
+ };
+
Unit *target;
Iterator i;
int r;
+ unsigned k;
assert(u);
- SET_FOREACH(target, u->meta.dependencies[UNIT_REQUIRED_BY], i)
- if ((r = unit_add_default_target_dependency(u, target)) < 0)
- return r;
-
- SET_FOREACH(target, u->meta.dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
- if ((r = unit_add_default_target_dependency(u, target)) < 0)
- return r;
-
- SET_FOREACH(target, u->meta.dependencies[UNIT_WANTED_BY], i)
- if ((r = unit_add_default_target_dependency(u, target)) < 0)
- return r;
-
- SET_FOREACH(target, u->meta.dependencies[UNIT_BOUND_BY], i)
- if ((r = unit_add_default_target_dependency(u, target)) < 0)
- return r;
+ for (k = 0; k < ELEMENTSOF(deps); k++)
+ SET_FOREACH(target, u->meta.dependencies[deps[k]], i)
+ if ((r = unit_add_default_target_dependency(u, target)) < 0)
+ return r;
return 0;
}
return r;
}
+bool unit_condition_test(Unit *u) {
+ assert(u);
+
+ dual_timestamp_get(&u->meta.condition_timestamp);
+ u->meta.condition_result = condition_test_list(u->meta.conditions);
+
+ return u->meta.condition_result;
+}
+
/* Errors:
* -EBADR: This unit type does not support starting.
* -EALREADY: Unit is already started.
return -EALREADY;
/* If the conditions failed, don't do anything at all */
- if (!condition_test_list(u->meta.conditions)) {
+ if (!unit_condition_test(u)) {
log_debug("Starting of %s requested but condition failed. Ignoring.", u->meta.id);
return -EALREADY;
}
unit_check_unneeded(other);
}
-void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
+void unit_trigger_on_failure(Unit *u) {
+ Unit *other;
+ Iterator i;
+
+ assert(u);
+
+ SET_FOREACH(other, u->meta.dependencies[UNIT_ON_FAILURE], i)
+ manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
+}
+
+void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
dual_timestamp ts;
bool unexpected;
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
+ * finished job, or maybe contradicts a running job and
* hence needs to invalidate jobs. */
switch (u->meta.job->type) {
case JOB_VERIFY_ACTIVE:
if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
- job_finish_and_invalidate(u->meta.job, true);
+ job_finish_and_invalidate(u->meta.job, JOB_DONE);
else if (u->meta.job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
unexpected = true;
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->meta.job, ns != UNIT_FAILED);
+ job_finish_and_invalidate(u->meta.job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE);
}
break;
if (u->meta.job->state == JOB_RUNNING) {
if (ns == UNIT_ACTIVE)
- job_finish_and_invalidate(u->meta.job, true);
+ job_finish_and_invalidate(u->meta.job, reload_success ? JOB_DONE : JOB_FAILED);
else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) {
unexpected = true;
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->meta.job, ns != UNIT_FAILED);
+ job_finish_and_invalidate(u->meta.job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE);
}
}
case JOB_TRY_RESTART:
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->meta.job, true);
+ job_finish_and_invalidate(u->meta.job, JOB_DONE);
else if (u->meta.job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
unexpected = true;
- job_finish_and_invalidate(u->meta.job, false);
+ job_finish_and_invalidate(u->meta.job, JOB_FAILED);
}
break;
}
if (ns != os && ns == UNIT_FAILED) {
- Iterator i;
- Unit *other;
-
- SET_FOREACH(other, u->meta.dependencies[UNIT_ON_FAILURE], i)
- manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
-
log_notice("Unit %s entered failed state.", u->meta.id);
+ unit_trigger_on_failure(u);
}
/* Some names are special */
/* The bus just might have become available,
* hence try to connect to it, if we aren't
* yet connected. */
- bus_init(u->meta.manager);
+ bus_init(u->meta.manager, true);
if (unit_has_name(u, SPECIAL_SYSLOG_SERVICE))
/* The syslog daemon just might have become