Fix race condition in AsyncResponder.resume() and cancel() by re-checking state under write lock#6083
Open
anuragg-saxenaa wants to merge 1 commit intoeclipse-ee4j:4.xfrom
Conversation
…e condition (eclipse-ee4j#6068) Both resume() and cancel() in AsyncResponder used a read-check/release/ write-acquire pattern without re-verifying state after obtaining the write lock. This created a window where: - Thread A (resume): reads SUSPENDED, releases read lock - Thread B (cancel): reads SUSPENDED, releases read lock - Thread A: acquires write lock, sets RESUMED - Thread B: acquires write lock, sets RESUMED again (+ cancelled) - Both threads proceed to process the response, double-processing Fix: add a second state check inside the write-lock critical section in both resume() and cancel(). If state changed between the read and write lock acquisitions, return false immediately. Also wrap write-lock body in try/finally to ensure the lock is always released. This is a standard double-checked locking fix for the check-then-act pattern with ReadWriteLock. Fixes eclipse-ee4j#6068 Signed-off-by: anuragg-saxenaa <anuragg.saxenaa@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ServerRuntime.AsyncResponderuses a read-check / release / write-acquire pattern in bothresume()andcancel(). A window exists between releasing the read lock and acquiring the write lock where another thread can change the state, making the initial check stale. This allows concurrentresume()andcancel()calls to both proceed past the state check and both setstate = RESUMED, resulting in double-processing of a response.Race scenario
resume()): acquires read lock → seesSUSPENDED→ releases read lockcancel()): acquires read lock → seesSUSPENDED→ releases read lockRESUMED→ releases write lock → processes responseRESUMED,cancelled = true→ processes response againFix
Add a second state check inside the write-lock critical section in both
resume()andcancel(). If state changed between the read and write lock acquisitions, returnfalseimmediately. Also wrapped write-lock body intry/finallyso the lock is always released even if an exception occurs in the re-check.This is the standard double-checked locking pattern for
ReadWriteLock.Fixes #6068