-
Notifications
You must be signed in to change notification settings - Fork 327
Async Servlet state management changes #385
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
Async Servlet state management changes #385
Conversation
Codecov Report
@@ Coverage Diff @@
## master #385 +/- ##
============================================
- Coverage 72.98% 71.97% -1.01%
+ Complexity 1248 1203 -45
============================================
Files 132 132
Lines 4738 4564 -174
Branches 515 468 -47
============================================
- Hits 3458 3285 -173
+ Misses 1068 1066 -2
- Partials 212 213 +1
Continue to review full report at Codecov.
|
|
//cc @adriancole |
|
thanks for the ping
|
felixbarny
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is still the potential race condition for the completed check in AsyncListener. Other than that LGTM.
| // (see class-level Javadoc) | ||
| private void endTransaction(AsyncEvent event) { | ||
| // To ensure transaction is ended only by a single event | ||
| if(EVENT_COUNTER_UPDATER.getAndIncrement(this) > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if(EVENT_COUNTER_UPDATER.getAndIncrement(this) > 0) { | |
| if (EVENT_COUNTER_UPDATER.getAndIncrement(this) > 0) { |
General
Investigation started due to #371
A race condition introduced due to implementation failure of some fine-grained definitions of the
HttpServletRequest.startAsyncAPI in some application servers requires a shift in how we instrument this. The full explanation is below, but the short version is-AsyncContext.isAsyncStartedis not fully reliable when invoked at the end ofservice/doFilterin whichHttpServletRequest.startAsyncwas used, due to race condition between both threads handling the request.Basic rationale behind the suggested solution: if
HttpServletRequest.startAsyncis used, then the transaction data should not be updated by theservice/doFilterinstrumentation route, but only through theAsyncListenerwe register. This should hold for allAsyncContextAPIs and regardless of multiple dispatches. Furthermore, we assume that if anAsyncListenerwas registered- it must be invoked when response gets committed, so we rely on it to clear states.Detailed explanation
The javadoc for
AsyncContext.isAsyncStartedsays that it will returnfalseafterAsyncContext.dispatchorAsyncContext.completeare invoked. Looking further into thedispatchandcompletejavadoc shows that this is a bit more complicated, as it says:This means that querying
AsyncContext.isAsyncStartedshould be safe at the end ofservice/doFilter, as the container should wait for those to return before actually invokingdispatch/complete. When testing multiple WildFly versions, I saw that while this is indeed the case withdispatch, it is not so in the case ofcomplete, at least in WildFly versions8 through 11. Specifically, the
AsyncContextoffers astartAPI for conveniently invoke logic on a separate thread, wherecompleteis likely to be called, making it a common use case.