Browse Source

Synchronize in WebAsyncManager onError/onTimeout

On connection loss, in a race between application thread and onError
callback trying to set the DeferredResult and dispatch, the onError
callback must not exit until dispatch completes. Currently, it may do
so because the DeferredResult has checks to bypasses locking or even
trying to dispatch if result is already set.

Closes gh-34192
pull/34398/head
rstoyanchev 12 months ago
parent
commit
6ec7dcf2c1
  1. 10
      spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java

10
spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java

@ -427,6 +427,11 @@ public final class WebAsyncManager { @@ -427,6 +427,11 @@ public final class WebAsyncManager {
}
try {
interceptorChain.triggerAfterTimeout(this.asyncWebRequest, deferredResult);
synchronized (WebAsyncManager.this) {
// If application thread set the DeferredResult first in a race,
// we must still not return until setConcurrentResultAndDispatch is done
return;
}
}
catch (Throwable ex) {
setConcurrentResultAndDispatch(ex);
@ -439,6 +444,11 @@ public final class WebAsyncManager { @@ -439,6 +444,11 @@ public final class WebAsyncManager {
}
try {
interceptorChain.triggerAfterError(this.asyncWebRequest, deferredResult, ex);
synchronized (WebAsyncManager.this) {
// If application thread set the DeferredResult first in a race,
// we must still not return until setConcurrentResultAndDispatch is done
return;
}
}
catch (Throwable interceptorEx) {
setConcurrentResultAndDispatch(interceptorEx);

Loading…
Cancel
Save