diff --git a/man/sd_notify.xml b/man/sd_notify.xml index e8ddea2f5fb..7d7b0077bec 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -139,7 +139,8 @@ present it to the user. Note that a service that sends this notification must also send a READY=1 notification when it completed reloading its - configuration. + configuration. Reloads are propagated in the same way as they + are when initiated by the user. diff --git a/src/core/manager.c b/src/core/manager.c index fb5e2b55132..7f9c6164c71 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1494,6 +1494,40 @@ int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, return r; } +int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e) { + int r; + Transaction *tr; + + assert(m); + assert(unit); + assert(mode < _JOB_MODE_MAX); + assert(mode != JOB_ISOLATE); /* Isolate is only valid for start */ + + tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY); + if (!tr) + return -ENOMEM; + + /* We need an anchor job */ + r = transaction_add_job_and_dependencies(tr, JOB_NOP, unit, NULL, false, false, true, true, e); + if (r < 0) + goto tr_abort; + + /* Failure in adding individual dependencies is ignored, so this always succeeds. */ + transaction_add_propagate_reload_jobs(tr, unit, tr->anchor_job, mode == JOB_IGNORE_DEPENDENCIES, e); + + r = transaction_activate(tr, m, mode, e); + if (r < 0) + goto tr_abort; + + transaction_free(tr); + return 0; + +tr_abort: + transaction_abort(tr); + transaction_free(tr); + return r; +} + Job *manager_get_job(Manager *m, uint32_t id) { assert(m); diff --git a/src/core/manager.h b/src/core/manager.h index 6aceed281a1..5146a795f1d 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -344,6 +344,7 @@ int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret); int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **_ret); int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret); +int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e); void manager_dump_units(Manager *s, FILE *f, const char *prefix); void manager_dump_jobs(Manager *s, FILE *f, const char *prefix); diff --git a/src/core/service.c b/src/core/service.c index baeed70554e..39fcdcc1a76 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1945,10 +1945,18 @@ fail: } static void service_enter_reload_by_notify(Service *s) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + assert(s); service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_start_usec)); service_set_state(s, SERVICE_RELOAD); + + /* service_enter_reload_by_notify is never called during a reload, thus no loops are possible. */ + r = manager_propagate_reload(UNIT(s)->manager, UNIT(s), JOB_FAIL, &error); + if (r < 0) + log_unit_warning(UNIT(s), "Failed to schedule propagation of reload: %s", bus_error_message(&error, -r)); } static void service_enter_reload(Service *s) { diff --git a/src/core/transaction.c b/src/core/transaction.c index 710a6a39489..1af4ed91006 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -858,6 +858,30 @@ static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependen } } +void transaction_add_propagate_reload_jobs(Transaction *tr, Unit *unit, Job *by, bool ignore_order, sd_bus_error *e) { + Iterator i; + Unit *dep; + JobType nt; + int r; + + assert(tr); + assert(unit); + + SET_FOREACH(dep, unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) { + nt = job_type_collapse(JOB_TRY_RELOAD, dep); + if (nt == JOB_NOP) + continue; + + r = transaction_add_job_and_dependencies(tr, nt, dep, by, false, false, false, ignore_order, e); + if (r < 0) { + log_unit_warning(dep, + "Cannot add dependency reload job, ignoring: %s", + bus_error_message(e, r)); + sd_bus_error_free(e); + } + } +} + int transaction_add_job_and_dependencies( Transaction *tr, JobType type, @@ -1043,24 +1067,8 @@ int transaction_add_job_and_dependencies( } } - if (type == JOB_RELOAD) { - - SET_FOREACH(dep, ret->unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) { - JobType nt; - - nt = job_type_collapse(JOB_TRY_RELOAD, dep); - if (nt == JOB_NOP) - continue; - - r = transaction_add_job_and_dependencies(tr, nt, dep, ret, false, false, false, ignore_order, e); - if (r < 0) { - log_unit_warning(dep, - "Cannot add dependency reload job, ignoring: %s", - bus_error_message(e, r)); - sd_bus_error_free(e); - } - } - } + if (type == JOB_RELOAD) + transaction_add_propagate_reload_jobs(tr, ret->unit, ret, ignore_order, e); /* JOB_VERIFY_STARTED require no dependency handling */ } diff --git a/src/core/transaction.h b/src/core/transaction.h index 6a3f927b0f3..ddfdbf9987e 100644 --- a/src/core/transaction.h +++ b/src/core/transaction.h @@ -36,6 +36,7 @@ struct Transaction { Transaction *transaction_new(bool irreversible); void transaction_free(Transaction *tr); +void transaction_add_propagate_reload_jobs(Transaction *tr, Unit *unit, Job *by, bool ignore_order, sd_bus_error *e); int transaction_add_job_and_dependencies( Transaction *tr, JobType type,