}
static int make_unit_name(sd_bus *bus, UnitType t, char **ret) {
+ unsigned soft_reboots_count = 0;
const char *unique, *id;
char *p;
int r;
"Unique name %s has unexpected format.",
unique);
- p = strjoin("run-u", id, ".", unit_type_to_string(t));
- if (!p)
- return log_oom();
+ /* The unique D-Bus names are actually unique per D-Bus instance, so on soft-reboot they will wrap
+ * and start over since the D-Bus broker is restarted. If there's a failed unit left behind that
+ * hasn't been garbage collected, we'll conflict. Append the soft-reboot counter to avoid clashing. */
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ r = bus_get_property_trivial(
+ bus, bus_systemd_mgr, "SoftRebootsCount", &error, 'u', &soft_reboots_count);
+ if (r < 0)
+ log_debug_errno(r, "Failed to get SoftRebootsCount property, ignoring: %s", bus_error_message(&error, r));
+
+ if (soft_reboots_count > 0) {
+ if (asprintf(&p, "run-u%s-s%u.%s", id, soft_reboots_count, unit_type_to_string(t)) < 0)
+ return log_oom();
+ } else {
+ p = strjoin("run-u", id, ".", unit_type_to_string(t));
+ if (!p)
+ return log_oom();
+ }
*ret = p;
return 0;
# Restart the unit that is not supposed to survive
systemd-run --collect --service-type=exec --unit=testsuite-82-nosurvive.service sleep infinity
+ # Now ensure there are no naming clashes and a bunch of transient units all succeed
+ for _ in $(seq 1 25); do
+ systemd-run --wait true
+ done
+
# Now issue the soft reboot. We should be right back soon. Given /run/nextroot exists, we should
# automatically do a softreboot instead of normal reboot.
touch /run/testsuite82.touch2
systemd-inhibit --what=shutdown --who=test --why=test --mode=delay \
sleep infinity
+ # Enqueue a bunch of failing units to try and trigger the transient name clash that happens due to D-Bus
+ # being restarted and the "unique" bus IDs not being unique across restarts
+ for _ in $(seq 1 25); do
+ # Use --wait to ensure we connect to the system bus instead of the private bus (otherwise a UUID is
+ # used instead of the bus ID)
+ systemd-run --wait false || true
+ done
+
# Now issue the soft reboot. We should be right back soon.
touch /run/testsuite82.touch
systemctl --no-block --check-inhibitors=yes soft-reboot