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,