Skip to content
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

DefaultMessageListenerContainer doesn't shutdown gracefully if long recovery interval is set [SPR-14200] #18774

spring-issuemaster opened this issue Apr 21, 2016 · 2 comments


Copy link

@spring-issuemaster spring-issuemaster commented Apr 21, 2016

Oleg Ivanov opened SPR-14200 and commented

Currently in DefaultMessageListenerContainer.applyBackOffTime(BackOffExecution execution) function the current thread is sleeping during the back off interval. This prevents container to shutdown correctly (as it waits for this thread to wake up).

I suggest to rewrite this function using .wait() calls:

        final long interval = execution.nextBackOff();
        if (interval == BackOffExecution.STOP)
            return false;

        if (isRecovering() && interrupted)
            // Interrupted right before and still failing... give up.
            return false;

        try {
            synchronized (this.lifecycleMonitor) {
                final long start = System.currentTimeMillis();
                while (isActive() && System.currentTimeMillis() - start < interval) {
                    final long timeout = getReceiveTimeout();
                    this.lifecycleMonitor.wait(timeout > 0 ? timeout : DEFAULT_RECEIVE_TIMEOUT);
        } catch (InterruptedException interEx) {
            // Re-interrupt current thread, to allow other threads to react.
            if (isRecovering())
                this.interrupted = true;

        return true;

Affects: 4.2.5

Issue Links:

  • #16409 DefaultMessageListenerContainer hangs on shutdown
  • #16460 DefaultMessageListenerContainer#doShutdown hangs
  • #18799 Client-side polling delay as alternative for receive timeout for JMS

Referenced from: commits 6ab8d36

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Apr 27, 2016

Juergen Hoeller commented

To the best of my understanding, a simple switch to lifecycleMonitor.wait(recoveryInterval) should do the job, allowing for notifyAll to reach it. During a recovery phase, our invoker infrastructure just triggers such a notification in case of a stop call or a full shutdown, both of which turn isRunning to false... so if applyBackOffTime exits normally, the surrounding loop will automatically check isRunning and end the refresh attempt.

I've implemented this for 4.3 RC2. Feel free to give the upcoming 4.3.0.BUILD-SNAPSHOT an early try...

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Apr 29, 2016

Oleg Ivanov commented

Hi, Juergen, you are right - lifecycleMonitor.wait(interval) is enough. I didn't realize this monitor can be used. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.