Xamarin-android: NetworkOnMainThreadException in AndroidClientHandler on cancellation

Created on 20 Apr 2018  路  3Comments  路  Source: xamarin/xamarin-android

Steps to Reproduce

Unfortunately, I'm not able to reproduce this error myself as it works fine on my devices. I got the error report from App Center.

Expected Behavior

Cancelling HTTP task from main thread should not cause NetworkOnMainThreadException. Actual HTTP task is launched from another thread.

Actual Behavior

ExceptionDispatchInfo.Throw ()
JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args)
JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters)
HttpsURLConnectionInvoker.Disconnect ()
AndroidClientHandler+<>c__DisplayClass42_0.<ConnectAsync>b__1 ()
CancellationToken.ActionToActionObjShunt (System.Object obj)
CancellationCallbackInfo.ExecutionContextCallback (System.Object obj)
ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx)
ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx)
ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state)
CancellationCallbackInfo.ExecuteCallback ()
CancellationTokenSource.CancellationCallbackCoreWork (System.Threading.CancellationCallbackCoreWorkArguments args)
CancellationTokenSource.ExecuteCallbackHandlers (System.Boolean throwOnFirstException)


android.os.NetworkOnMainThreadException
android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1166)
com.android.org.conscrypt.OpenSSLSocketImpl.close(OpenSSLSocketImpl.java:1010)
com.android.okhttp.Connection.close(Connection.java:175)
com.android.okhttp.internal.Util.closeQuietly(Util.java:110)
com.android.okhttp.internal.http.HttpEngine.release(HttpEngine.java:447)
com.android.okhttp.internal.http.HttpURLConnectionImpl.disconnect(HttpURLConnectionImpl.java:104)
com.android.okhttp.internal.http.HttpsURLConnectionImpl.disconnect(HttpsURLConnectionImpl.java:124)
mono.android.view.View_OnClickListenerImplementor.n_onClick(Native Method)
mono.android.view.View_OnClickListenerImplementor.onClick(View_OnClickListenerImplementor.java:30)
android.view.View.performClick(View.java:4640)
android.view.View$PerformClick.run(View.java:19425)
android.os.Handler.handleCallback(Handler.java:733)
android.os.Handler.dispatchMessage(Handler.java:95)
android.os.Looper.loop(Looper.java:146)
android.app.ActivityThread.main(ActivityThread.java:5593)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:515)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
dalvik.system.NativeStart.main(Native Method)

Version Information

This happens on devices from KitKat to Nougat. No info on Oreo.

App has been built on App Center with Xamarin.Android 8.2, Mono 5.8.

VS bug #645997

vs-sync

Most helpful comment

We are facing the same issue on build Mono 5.10.1.57 (2017-12/ea8a24b1bbf) (64-bit) -- Xamarin.Android Version: 8.3.3.2, our stack trace says:

ExceptionDispatchInfo.Throw ()
2 JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args)
3 JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters)
4 HttpsURLConnectionInvoker.Disconnect ()
5 AndroidClientHandler+<>c__DisplayClass42_0.<ConnectAsync>b__1 ()
6 CancellationToken.ActionToActionObjShunt (System.Object obj)
7 CancellationCallbackInfo.ExecutionContextCallback (System.Object obj)

Looking at https://github.com/xamarin/xamarin-android/blob/master/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs#L305 - pointed by step 5 (ConnectAsync) on the stack trace - it register a temporary cancellation callback doing a straight call to httpConnection?.Disconnect () what means it will run on whatever thread the Cancel() was called on the CancellationSource.

But on the same file we can find on the DoProcessRequest a similar call: https://github.com/xamarin/xamarin-android/blob/master/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs#L381 but this time making use of the DisconnectAsync that makes sure the disconnect do not happen on the main thread.

We did a pull request to fix it in https://github.com/xamarin/xamarin-android/pull/1925

All 3 comments

We are facing the same issue on build Mono 5.10.1.57 (2017-12/ea8a24b1bbf) (64-bit) -- Xamarin.Android Version: 8.3.3.2, our stack trace says:

ExceptionDispatchInfo.Throw ()
2 JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args)
3 JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters)
4 HttpsURLConnectionInvoker.Disconnect ()
5 AndroidClientHandler+<>c__DisplayClass42_0.<ConnectAsync>b__1 ()
6 CancellationToken.ActionToActionObjShunt (System.Object obj)
7 CancellationCallbackInfo.ExecutionContextCallback (System.Object obj)

Looking at https://github.com/xamarin/xamarin-android/blob/master/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs#L305 - pointed by step 5 (ConnectAsync) on the stack trace - it register a temporary cancellation callback doing a straight call to httpConnection?.Disconnect () what means it will run on whatever thread the Cancel() was called on the CancellationSource.

But on the same file we can find on the DoProcessRequest a similar call: https://github.com/xamarin/xamarin-android/blob/master/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs#L381 but this time making use of the DisconnectAsync that makes sure the disconnect do not happen on the main thread.

We did a pull request to fix it in https://github.com/xamarin/xamarin-android/pull/1925

Pull 1925 fixed this issue, thanks @Flash3001!

Fix cherry-picked to the 15.8 (upcoming release) branch

Was this page helpful?
0 / 5 - 0 ratings