core: introduce Unit.dependency_generation counter and restart loop when dependency is updated in the loop

When starting unit A, a dependent unit B may be loaded if it is not
loaded yet, and the dependencies in unit A may be updated.
As Hashmap does not allow a new entry to be added in a loop, we need to
restart loop in such case.

Fixes a bug introduced by cda667722c.
Fixes #36031.
This commit is contained in:
Yu Watanabe
2025-05-29 05:41:25 +09:00
parent 9b6aa9e443
commit b7777d0884
3 changed files with 45 additions and 14 deletions
+10
View File
@@ -631,12 +631,14 @@ static void unit_clear_dependencies(Unit *u) {
hashmap_remove(other_deps, u);
unit_add_to_gc_queue(other);
other->dependency_generation++;
}
hashmap_free(deps);
}
u->dependencies = hashmap_free(u->dependencies);
u->dependency_generation++;
}
static void unit_remove_transient(Unit *u) {
@@ -1094,6 +1096,9 @@ static void unit_merge_dependencies(Unit *u, Unit *other) {
}
other->dependencies = hashmap_free(other->dependencies);
u->dependency_generation++;
other->dependency_generation++;
}
int unit_merge(Unit *u, Unit *other) {
@@ -3088,6 +3093,7 @@ static int unit_add_dependency_impl(
return r;
flags = NOTIFY_DEPENDENCY_UPDATE_FROM;
u->dependency_generation++;
}
if (other_info.data != other_info_old.data) {
@@ -3104,6 +3110,7 @@ static int unit_add_dependency_impl(
}
flags |= NOTIFY_DEPENDENCY_UPDATE_TO;
other->dependency_generation++;
}
return flags;
@@ -5618,6 +5625,9 @@ void unit_remove_dependencies(Unit *u, UnitDependencyMask mask) {
/* The unit 'other' may not be wanted by the unit 'u'. */
unit_submit_to_stop_when_unneeded_queue(other);
u->dependency_generation++;
other->dependency_generation++;
done = false;
break;
}