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

Field eventsToDeliver is a LinkedList, i.e., not thread-safe. Accesses to field eventsToDeliver are protected by synchronization on itself, but not in 1 location. #1971

Merged
merged 6 commits into from
Oct 30, 2020

Conversation

adriannistor
Copy link
Contributor

@adriannistor adriannistor commented Aug 3, 2020

I also reported this at:

#1972

Description

Field eventsToDeliver is a LinkedList (line 128), i.e., not thread-safe.

Accesses to eventsToDeliver are protected by synchronization on itself (synchronized (eventsToDeliver)), e.g., at lines: 373-376, 424-426, 493-494, 493-498, and 493-506.

Note that line 506 (a remove()) and line 374 (decoder calls handleMessage() as per decoder's definition at line 110, and handleMessage() calls add() at line 271) modify the eventsToDeliver (and are protected by synchronization at line 493 and line 373 respectively).

However, line 397 (an add(), i.e., modifies eventsToDeliver) is not protected.

I see line 397 adds a ON_COMPLETE_EVENT, which, when processed in the eventsToDeliver, will signal termination (in isCompletedOrDeliverEvent() at line 494).

However, I think the add() at line 397 can occur in parallel with the remove() at line 506. This is because the remove() at line 506 occurs for other messages in the eventsToDeliver that were already enqueued before the ON_COMPLETE_EVENT.

I.e., when ON_COMPLETE_EVENT is being added by line 397 other messages may still be getting processed from the eventsToDeliver queue.

Note how isCompletedOrDeliverEvent() is getting called (by itself, recursively) at lines 505-509 until eventsToDeliver becomes empty (line 498) or ON_COMPLETE_EVENT is encountered (line 494).

Note also how the recursive calls at lines 505-509 are asynchronous (which is likely part of the reason for which we have the synchronization).

Even if somehow we know that there is a guarantee that all calls to line 506 were finished before line 397 is called (seems unlikely, with all those asynchronous calls above---also, if we could enforce such a guarantee, we may have better ways to communicate completion than to enqueue ON_COMPLETE_EVENT in the shared eventsToDeliver queue), it still seems like a fragile guarantee to make, because external callers may not be aware of it (e.g., it is not documented) or about other timing assumptions.

This Fix Code

This fix is very simple: just surround the add() at line 397 with a synchronized (eventsToDeliver), just like the other lines discussed above (373-376, 424-426, 493-494, 493-498, and 493-506).

Testing

mvn clean install

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Checklist

  • I have read the CONTRIBUTING document
  • Local run of mvn install succeeds
  • My code follows the code style of this project
  • My change requires a change to the Javadoc documentation
  • I have updated the Javadoc documentation accordingly
  • I have read the README document
  • I have added tests to cover my changes
  • All new and existing tests passed
  • A short description of the change has been added to the CHANGELOG
  • My change is to implement 1.11 parity feature and I have updated LaunchChangelog

License

  • I confirm that this pull request can be released under the Apache 2 license

…s to field eventsToDeliver are protected by synchronization on itself, but not in 1 location.
@codecov-commenter
Copy link

codecov-commenter commented Aug 3, 2020

Codecov Report

Merging #1971 into master will increase coverage by 0.01%.
The diff coverage is 100.00%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #1971      +/-   ##
============================================
+ Coverage     76.63%   76.64%   +0.01%     
  Complexity      225      225              
============================================
  Files          1112     1112              
  Lines         33646    33586      -60     
  Branches       2606     2598       -8     
============================================
- Hits          25783    25742      -41     
+ Misses         6584     6563      -21     
- Partials       1279     1281       +2     
Flag Coverage Δ Complexity Δ
#unittests 76.64% <100.00%> (+0.01%) 225.00 <0.00> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ Complexity Δ
...entstream/EventStreamAsyncResponseTransformer.java 86.77% <100.00%> (+0.14%) 0.00 <0.00> (ø)
.../awssdk/http/apache/internal/net/SdkSslSocket.java 36.36% <0.00%> (-22.73%) 0.00% <0.00%> (ø%)
...ery/internal/marshall/QueryMarshallerRegistry.java 77.77% <0.00%> (-2.23%) 0.00% <0.00%> (ø%)
...awssdk/codegen/poet/client/specs/ProtocolSpec.java 83.33% <0.00%> (-1.78%) 0.00% <0.00%> (ø%)
...tials/WebIdentityTokenFileCredentialsProvider.java 35.55% <0.00%> (-1.66%) 0.00% <0.00%> (ø%)
...ty/internal/IdleConnectionCountingChannelPool.java 87.80% <0.00%> (-1.22%) 0.00% <0.00%> (ø%)
.../amazon/awssdk/http/apache/ProxyConfiguration.java 49.03% <0.00%> (-0.97%) 0.00% <0.00%> (ø%)
...internal/client/DefaultDynamoDbEnhancedClient.java 63.46% <0.00%> (-0.69%) 0.00% <0.00%> (ø%)
...k/enhanced/dynamodb/model/ScanEnhancedRequest.java 60.71% <0.00%> (-0.69%) 0.00% <0.00%> (ø%)
...ons/servicemetadata/EnhancedS3ServiceMetadata.java 88.23% <0.00%> (-0.66%) 0.00% <0.00%> (ø%)
... and 46 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3304935...26632f9. Read the comment docs.

@sonarcloud
Copy link

sonarcloud bot commented Aug 3, 2020

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 0 Code Smells

100.0% 100.0% Coverage
0.0% 0.0% Duplication

warning The version of Java (1.8.0_252) you have used to run this analysis is deprecated and we will stop accepting it from October 2020. Please update to at least Java 11.
Read more here

@millems
Copy link
Contributor

millems commented Oct 23, 2020

Reviewing this. It looks like it shouldn't happen today, but that doesn't mean it shouldn't happen in the future. Should we also guard line 271 (a eventsToDeliver.add) with a synchronized block?

Can we also amend the release note to specify it's a "future race condition risk", since it's not a race condition today?

@millems
Copy link
Contributor

millems commented Oct 29, 2020

Comments above are minor, so I'll probably just merge it as-is since it seems like the customer might not have time to get back on this issue.

@zoewangg
Copy link
Contributor

We might need to update the changelog entry to add the contributor though, otherwise changelog script might fail.

@sonarcloud
Copy link

sonarcloud bot commented Oct 30, 2020

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 0 Code Smells

100.0% 100.0% Coverage
0.0% 0.0% Duplication

@millems millems merged commit 944c2f5 into aws:master Oct 30, 2020
aws-sdk-java-automation added a commit that referenced this pull request Mar 24, 2022
…1d62f0f6a

Pull request: release <- staging/39b5da9e-12d6-48f4-9c40-be41d62f0f6a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants