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

NetworkOnMainThreadException thrown when EnsureSuccessStatusCode is called #4691

Closed
Flash3001 opened this issue May 15, 2020 · 3 comments
Closed
Assignees

Comments

@Flash3001
Copy link
Contributor

Steps to Reproduce

  1. Send a new Http request using SendAsync with the HttpCompletionOption.ResponseHeadersRead option.
  2. The server response needs to be a non-2xx code with a big payload (don't know how big, we tested with 5MB, a few bytes won't cause the issue)
  3. Call HttpResponseMessage.EnsureSuccessStatusCode() from the main thread.

Expected Behavior

A HttpRequestException should be thrown.

Actual Behavior

A Android.OS.NetworkOnMainThreadException is thrown.

Version Information

Mono Framework MDK
Runtime:
Mono 6.8.0.123 (2019-10/1d0d939dc30) (64-bit)
Package version: 608000123

Xamarin.Android
Version: 10.2.0.100 (Visual Studio Community)
Commit: xamarin-android/d16-5/988c811

Log File

Sample of of a stack trace:

Error in application
Exception of type 'Android.OS.NetworkOnMainThreadException' was thrown.
  at Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0006e] in <26521a5118b44c858c385715922b9d5d>:0 
  at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0002a] in <26521a5118b44c858c385715922b9d5d>:0 
  at Java.IO.InputStream.Close () [0x0000a] in <d3b924763d4a465c85b26f6e8edc8a53>:0 
  at Android.Runtime.InputStreamInvoker.Close () [0x00006] in <d3b924763d4a465c85b26f6e8edc8a53>:0 
  at System.IO.Stream.Dispose () [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2019-10/android/release/external/corert/src/System.Private.CoreLib/shared/System/IO/Stream.cs:236 
  at (wrapper remoting-invoke-with-check) System.IO.Stream.Dispose()
  at System.IO.BufferedStream.Dispose (System.Boolean disposing) [0x00013] in /Users/builder/jenkins/workspace/archive-mono/2019-10/android/release/external/corefx/src/System.Runtime.Extensions/src/System/IO/BufferedStream.cs:297 
  at System.IO.Stream.Close () [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2019-10/android/release/external/corert/src/System.Private.CoreLib/shared/System/IO/Stream.cs:230 
  at System.IO.Stream.Dispose () [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2019-10/android/release/external/corert/src/System.Private.CoreLib/shared/System/IO/Stream.cs:236 
  at (wrapper remoting-invoke-with-check) System.IO.Stream.Dispose()
  at System.Net.Http.StreamContent.Dispose (System.Boolean disposing) [0x00003] in /Users/builder/jenkins/workspace/archive-mono/2019-10/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/StreamContent.cs:82 
  at System.Net.Http.HttpContent.Dispose () [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2019-10/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpContent.cs:538 
  at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode () [0x00010] in /Users/builder/jenkins/workspace/archive-mono/2019-10/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpResponseMessage.cs:165 
  at FishAngler.Core.Services.RestService.ExecuteRequestAsync[T] (System.String url, System.Net.Http.HttpMethod method, System.String content, System.String paginationToken, System.String accessToken, System.Boolean shouldRefreshToken, System.Threading.CancellationToken cancellationToken, System.Collections.Generic.Dictionary`2[TKey,TValue] headers) [0x00409] in /Users/flash/Work/FishAngler/mobileapp/FishAngler.Core/Services/RestService.cs:286 
  at FishAngler.Core.Services.RestService.ExecuteRequestAsync[T] (System.String url, System.Net.Http.HttpMethod method, System.String content, System.String paginationToken, System.String accessToken, System.Boolean shouldRefreshToken, System.Int32 maxConnectTries, System.Threading.CancellationToken cancellationToken, System.Collections.Generic.Dictionary`2[TKey,TValue] headers) [0x00099] in /Users/flash/Work/FishAngler/mobileapp/FishAngler.Core/Services/RestService.cs:172 
  --- End of managed Android.OS.NetworkOnMainThreadException stack trace ---
android.os.NetworkOnMainThreadException
	at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513)
	at com.android.org.conscrypt.Platform.blockGuardOnNetwork(Platform.java:415)
	at com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream.read(ConscryptFileDescriptorSocket.java:560)
	at com.android.okhttp.okio.Okio$2.read(Okio.java:141)
	at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
	at com.android.okhttp.okio.RealBufferedSource.read(RealBufferedSource.java:60)
	at com.android.okhttp.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:602)
	at com.android.okhttp.internal.Util.skipAll(Util.java:172)
	at com.android.okhttp.internal.Util.discard(Util.java:154)
	at com.android.okhttp.internal.http.Http1xStream$FixedLengthSource.close(Http1xStream.java:619)
	at com.android.okhttp.okio.RealBufferedSource.close(RealBufferedSource.java:421)
	at com.android.okhttp.okio.RealBufferedSource$1.close(RealBufferedSource.java:409)
	at mono.java.lang.RunnableImplementor.n_run(Native Method)
	at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:30)
	at android.os.Handler.handleCallback(Handler.java:873)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loop(Looper.java:214)
	at android.app.ActivityThread.main(ActivityThread.java:7050)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)

More info

Our fix for that is just to make sure that code is running on another thread.

In the version of HttpResponseMessage that is being run the EnsureSuccessStatusCode method is calling Dispose() on its _content stream. Which down the line tries to read more content: https://github.com/duzechao/OKHttpUtils/blob/1c1ee3667737c67d0ff523658bb9acad769030f7/okhttp/src/main/java/okhttp3/internal/http/Http1xStream.java#L458-L465

Trying to read the code for HttpResponseMessage.cs caused some confusion was I don't know which on is really in use.

When I look at Mono repository with the tag 6.8.0.123 the Dispose is not being called.
https://github.com/mono/mono/blob/1d0d939dc30a5b56f478bc9f097cab146276b9af/mcs/class/System.Net.Http/System.Net.Http/HttpResponseMessage.cs#L118-L124

But when I disassemble the code on System.Net.Http.dll it is there:

		public HttpResponseMessage EnsureSuccessStatusCode()
		{
			if (!IsSuccessStatusCode)
			{
				if (_content != null)
				{
					_content.Dispose();
				}
				throw new HttpRequestException(string.Format(CultureInfo.InvariantCulture, "Response status code does not indicate success: {0} ({1}).", (int)_statusCode, ReasonPhrase));
			}
			return this;
		}

Resolved from:

Dependency "System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
        Resolved file path is "/Library/Frameworks/Mono.framework/External/xbuild-frameworks/MonoAndroid/v1.0/System.Net.Http.dll".

This issue started to appear for us not long ago so we were trying to check HttpResponseMessage code to know if there was regression in there where the Dispose() started to be called recently or if it is just hiding another issue on our side - which we can now investigate by avoiding Android.OS.NetworkOnMainThreadException from being thrown.

@Flash3001 Flash3001 added the Area: App Runtime Issues in `libmonodroid.so`. label May 15, 2020
@moljac
Copy link
Contributor

moljac commented May 18, 2020

Thanks for your feedback. We will look into the issue as soon as possible.

@moljac moljac assigned moljac and grendello and unassigned moljac May 18, 2020
@grendello
Copy link
Contributor

@Flash3001 This looks like a Mono issue, can you attach a simple repro which triggers the behavior? Thanks!

@grendello
Copy link
Contributor

I suppose the code and situation here is similar to #4695, if this is so @Flash3001, please refer to #4695 (comment) for a possible solution. If not, please reopen this issue and attach the requested information, thanks!

@grendello grendello removed Area: App Runtime Issues in `libmonodroid.so`. need-info Issues that need more information from the author. labels May 19, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Jun 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants