New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shedlock prevents Tomcat from graceful shutdown #159
Comments
Looks like when ConcurrentTaskScheduler is constructed using an empty constructor (bean is declared in RegisterDefaultTaskSchedulerPostProcessor class), it creates a ScheduledExecutorService instance in the setScheduledExecutor method (Executors.newSingleThreadScheduledExecutor() line):
The created ExecutorService instance never gets shut down and this probably prevents Tomcat from stopping. I managed to workaround the issue by creating TaskScheduler and ScheduledExecutorService as beans like this:
And now the RegisterDefaultTaskSchedulerPostProcessor uses my ScheduledExecutorService bean instead of creating a new one with empty constructor, Tomcat shuts down without problems. Probably because Spring destroys those beans when closing. I am not sure if this is going to have an impact on ShedLock though :( |
Thanks a lot for the investigation, will take a look at it |
I think this is more a Spring bug then ShedLock. It is easy to reproduce without using ShedLock at all, just by specyfiying the following bean in an application:
When there is a TaskScheduler bean declared in an application (which happens automatically when ShedLock is enabled), then the ExecutorService does not get shut down when Spring shuts down. There is a method scheduleTasks in ScheduledTaskRegistrar, and when there is a TaskScheduler bean in an application, it does not create it's own ExecutorService object in below code:
and when this bean is destroyed, the destroy method does not call shutdown on ExecutorService:
I think that the ConcurrentTaskScheduler should implement the shutdown method that would call shutdown on it's internal ExecutorService field, for example
This method should be called from destroy method in ScheduledTaskRegistrar when Spring shuts down. This is probably not an issue in Spring apps running on embedded container, because they are usually closed by sending SIGTERM to the process (like pressing CTRL+C in a console) which causes the shutdown hooks to be executed. ExecutorService implementations probably have their own shut down hooks and close themselves automatically when the JVM is shutting down. |
You are right, |
You could consider instantiating your own ScheduledExecutorService bean, conditional on missing bean of the same type in case someone wanted to use their own bean. |
I found this part too and was surprised; this is quite invasive behavior. Normally you'd expect user to set up their context properly and throw an initialization error if not. Right now, for example, @scheduled annotations would work if this library was added as a maven dependency, but if a user chose to remove it, they would be broken, too. |
Sorry, I do not understand. Schedulled annotations work without ShedLock by instantiating an internal TaskScheduler. ShedLock just needs to create a TaskScheduler bean to make it work together |
Sorry, i had some weird/bad experiences when configuring concurrent scheduling in spring-boot (the default is single-threaded). It's just not as clearly defined what and how to do as one would expect. I ended up fiddling with Hence my wondering that if shedlock does some of this configuration for the user, and he/she starts depending on this, it can lead to random weird failures if/when this autoconfig is removed for any reason (removal of lib, or maybe you choose to remove it in a newer version?). Anyway, it's already there, so it doesn't matter, just generally, I prefer not to create such situations, as it's really hard to debug, being non-intuitive. |
I see, I will try to document it better. |
Since version 4.0.0 the default intercept mode is PROXY_METHOD which does not meddle with the task scheduler. |
When using Shedlock in a Spring Boot app run on external Tomcat, the Tomcat fails to shutdown gracefully and has to be killed.
Steps to reproduce:
It should get stuck and the last log seen should be like the one below:
demo.zip
The text was updated successfully, but these errors were encountered: