Application stuck on shutdown if ConcurrentTaskScheduler is used and application has startup error.

Reproducer repository: https://github.com/alexey-anufriev/spring-shutdown-stuck-with-custom-scheduler

Readme: https://github.com/alexey-anufriev/spring-shutdown-stuck-with-custom-scheduler/blob/master/README.md

Comment From: snicoll

That sounds like the expected behavior to me. The non-working example is creating a task scheduler manually. You're then responsible to shut it down, which happens automatically when exposed as a @Bean.

Comment From: alexey-anufriev

hi @snicoll,

here is attempt to fix it: https://github.com/alexey-anufriev/spring-shutdown-stuck-with-custom-scheduler/commit/828bf9f71b6e592030c9b0cb856eccb8a93bf57a

but the behavior is still the same

Comment From: philwebb

@alexey-anufriev I'm trying to reproduce the error, but I can't get it to fail in the IDE or by using java -jar. I do see things hang when using ./mvnw spring-boot:run. Are you seeing the problem in production, or is it only when using ./mvnw spring-boot:run?

Comment From: alexey-anufriev

@philwebb, you can check my README: https://github.com/alexey-anufriev/spring-shutdown-stuck-with-custom-scheduler/blob/master/README.md

or just run ./mvnw clean spring-boot:run -Dspring-boot.run.profiles=non-working

it is important to have a profile enabled.

Comment From: philwebb

@alexey-anufriev I did that and replicated the problem when using ./mvnw spring-boot:run but I'm trying to find out if the problem happens outside of that. When I tried java -jar -Dspring-boot.run.profiles=non-working ./target/spring-shutdown-stuck-0.0.1-SNAPSHOT.jar the application didn't hang. Neither did it hang in the IDE with that profile active.

Comment From: snicoll

@philwebb that's because -Dspring-boot.run.profiles is specific to the Maven plugin. Setting that property in your IDE or when invoking a repackaged archive has no effect.

@alexey-anufriev my initial comment still stands. ConcurrentTaskScheduler is primarily meant for wrapping an existing ScheduledExecutorService. The default constructor though creates an internal default executor, with no way to shut it down. In your custom arrangement, we'd really recommend you to use ThreadPoolTaskScheduler. If you insist on using ConcurrentTaskScheduler then you should use the constructor that takes a ScheduledExecutorService and shut it down yourself.

I've created https://github.com/spring-projects/spring-framework/issues/27914 to improve things in that area.

Comment From: alexey-anufriev

@snicoll, my initial thought was that spring boot just missed to close ConcurrentTaskScheduler but it turns out that this is rather a limitation of ConcurrentTaskScheduler. In any case, thank you for the issue you created and for the explanations.