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

Closed
spring-projects-issues opened this issue Apr 21, 2016 · 2 comments
Assignees
Labels
in: messaging Issues in messaging modules (jms, messaging) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues 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.
            Thread.currentThread().interrupt();
            if (isRecovering())
                this.interrupted = true;
        }

        return true;

Affects: 4.2.5

Issue Links:

Referenced from: commits 6ab8d36

@spring-projects-issues
Copy link
Collaborator Author

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...

@spring-projects-issues
Copy link
Collaborator Author

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
Labels
in: messaging Issues in messaging modules (jms, messaging) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants