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

[Mono.Android] Fix race condition in AndroidMessageHandler #8753

Conversation

simonrozsival
Copy link
Contributor

Fixes #8740

There is a race condition in AndroidMessageHandler (see #8740 (comment) for more information). The solution is fairly simple: we should determine the decompression strategy only during the setup, when AutomaticDecompression is set. We don't need to do any more work during the request.

To prevent changing the decompression strategy while there are requests mid-flight, the setter will only accept values until the first request is sent. This is exactly what the SocketsHttpHandler does. I didn't want to touch any code unrelated to the race condition in this PR so if we want to prevent other properties from being mutated while HTTP requests are being sent, we should do it in a follow-up PR.

/cc @grendello

@grendello
Copy link
Member

/azp run

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@tipa
Copy link

tipa commented Feb 23, 2024

Thanks for the quick fix. One small comment/suggestion: Is the _acceptEncoding variable even needed now or wouldn't it be easier to check for _acceptEncoding == null instead?

if (!decompress_here || String.IsNullOrEmpty (httpConnection.ContentEncoding)) {

@simonrozsival
Copy link
Contributor Author

@tipa Yes, we could replace decompress_here with _acceptEncoding is not null && _acceptEncoding != IDENTITY_ENCODING 👍

@grendello
Copy link
Member

/azp run

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonpryor
Copy link
Member

@grendello, @simonrozsival: is there any reasonable way to write a unit test for this?

@simonrozsival
Copy link
Contributor Author

@jonpryor I haven't come up with a good way to test this. The repro project needs to send several hundreds of requests before it hits the race condition. We could probably use HttpListener and hammer it with requests for several seconds with ~20 threads and make sure all the responses are automatically decompressed.

@grendello
Copy link
Member

@jonpryor I don't think there is such a way. What @simonrozsival proposes would sometimes work and would sometimes fail - another test we learn to ignore. No point IMO.

@tipa
Copy link

tipa commented Mar 4, 2024

Any chance this will be merged and released before .NET 9? :)

@grendello grendello merged commit e41a31b into xamarin:main Mar 5, 2024
47 checks passed
grendello added a commit that referenced this pull request Mar 6, 2024
* main:
  [Mono.Android] Fix race condition in AndroidMessageHandler (#8753)
  [ci] Fix SDL Sources Analysis for PRs from forks (#8785)
  [ci] Add 1ESPT override to MSBuild test stages (#8784)
  [ci] Do not use @self annotation for templates (#8783)
  [ci] Migrate to the 1ES template (#8747)
  [Mono.Android] fix trimming warnings, part 2 (#8758)
  [Xamarin.Android.Build.Tasks] set `%(DefineConstantsOnly)` for older API levels (#8777)
  [tests] fix duplicate sources in `NuGet.config` (#8772)
  Bump to xamarin/monodroid@e13723e701 (#8771)
grendello added a commit that referenced this pull request Mar 7, 2024
* main:
  [Mono.Android] Fix race condition in AndroidMessageHandler (#8753)
  [ci] Fix SDL Sources Analysis for PRs from forks (#8785)
  [ci] Add 1ESPT override to MSBuild test stages (#8784)
  [ci] Do not use @self annotation for templates (#8783)
  [ci] Migrate to the 1ES template (#8747)
  [Mono.Android] fix trimming warnings, part 2 (#8758)
grendello added a commit to grendello/xamarin-android that referenced this pull request Mar 8, 2024
* main: (306 commits)
  [templates] Remove redundant "template" from display name. (xamarin#8773)
  Bump to xamarin/java.interop@a7e09b7 (xamarin#8793)
  [build] Include MIT license in most NuGet packages (xamarin#8787)
  Bump to dotnet/installer@893b762b6e 9.0.100-preview.3.24153.2 (xamarin#8782)
  [docs] update notes about `dotnet-trace` and `dotnet-gcdump` (xamarin#8713)
  [Mono.Android] Fix race condition in AndroidMessageHandler (xamarin#8753)
  [ci] Fix SDL Sources Analysis for PRs from forks (xamarin#8785)
  [ci] Add 1ESPT override to MSBuild test stages (xamarin#8784)
  [ci] Do not use @self annotation for templates (xamarin#8783)
  [ci] Migrate to the 1ES template (xamarin#8747)
  [Mono.Android] fix trimming warnings, part 2 (xamarin#8758)
  [Xamarin.Android.Build.Tasks] set `%(DefineConstantsOnly)` for older API levels (xamarin#8777)
  [tests] fix duplicate sources in `NuGet.config` (xamarin#8772)
  Bump to xamarin/monodroid@e13723e701 (xamarin#8771)
  Bump to xamarin/xamarin-android-tools@37d79c9 (xamarin#8752)
  Bump to dotnet/installer@d070660282 9.0.100-preview.3.24126.2 (xamarin#8763)
  Bump to xamarin/java.interop@14a9470 (xamarin#8766)
  $(AndroidPackVersionSuffix)=preview.3; net9 is 34.99.0.preview.3 (xamarin#8765)
  [Mono.Android] Do not dispose request content stream in AndroidMessageHandler (xamarin#8764)
  Bump com.android.tools:r8 from 8.2.42 to 8.2.47 (xamarin#8761)
  ...
jonathanpeppers pushed a commit that referenced this pull request Mar 11, 2024
Fixes: #8740

There is a race condition in `AndroidMessageHandler` (see #8740 (comment) 
for more information). 

The solution is fairly simple: we should determine the decompression strategy only during the setup, when `AutomaticDecompression` is set. 
We don't need to do any more work during the request.

To prevent changing the decompression strategy while there are requests mid-flight, the setter will only accept values until the first request 
is sent. This is exactly what the `SocketsHttpHandler` does. I didn't want to touch any code unrelated to the race condition in this PR so if we 
want to prevent other properties from being mutated while HTTP requests are being sent, we should do it in a follow-up PR.
grendello added a commit that referenced this pull request Mar 11, 2024
* main:
  [templates] Remove redundant "template" from display name. (#8773)
  Bump to xamarin/java.interop@a7e09b7 (#8793)
  [build] Include MIT license in most NuGet packages (#8787)
  Bump to dotnet/installer@893b762b6e 9.0.100-preview.3.24153.2 (#8782)
  [docs] update notes about `dotnet-trace` and `dotnet-gcdump` (#8713)
  [Mono.Android] Fix race condition in AndroidMessageHandler (#8753)
  [ci] Fix SDL Sources Analysis for PRs from forks (#8785)
  [ci] Add 1ESPT override to MSBuild test stages (#8784)
  [ci] Do not use @self annotation for templates (#8783)
  [ci] Migrate to the 1ES template (#8747)
@github-actions github-actions bot locked and limited conversation to collaborators Apr 5, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[AndroidMessageHandler] ReadAsByteArrayAsync occasionally returning incorrect byte array
4 participants