-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Markus Heiden opened SPR-16901 and commented
DefaultLifecycleProcessor.LifecycleGroup#stop() fails to wait for all members, if there are dependencies between the members.
IMO the problem lies in this loop of LifecycleGroup#stop():
for (LifecycleGroupMember member : this.members) {
if (this.lifecycleBeans.containsKey(member.name)) {
doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames);
}
else if (member.bean instanceof SmartLifecycle) {
// already removed, must have been a dependent
latch.countDown();
}
}The loop iterates all members. doStop() removes the current member and its dependent members from this.lifecycleBeans and passes a callback to all of them which counts the latch down. This way the latch gets counted down for the current member and its dependent members.
Later on when the iteration reaches one of the dependent members from above, the else block gets executed, because the dependent member has already been removed from this.lifecycleBeans. This counts the latch down again for the dependent member.
This way the latch reaches 0 before all beans called their stop callback and the application context gets destroyed even though some of the members are still running.
I don't understand why the else block is needed at all. IMO it should be simply removed.
Affects: 5.0.6
Issue Links:
- ApplicationContext very slow to shutdown with bean of type org.springframework.scheduling.quartz.SchedulerFactoryBean [SPR-6354] #11020 ApplicationContext very slow to shutdown with bean of type org.springframework.scheduling.quartz.SchedulerFactoryBean
- INT-4486 The SmartLifecycle.stop(Runnable callback) implementation must always call callback, in the end
Referenced from: commits 6f41d4e, b3ca2d5, b71795b, 6cf1978
0 votes, 5 watchers