Bug 15857 - HttpClient async cancellation of POST requests unreliable
Summary: HttpClient async cancellation of POST requests unreliable
Status: VERIFIED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: BCL Class Libraries ()
Version: 4.8.x
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: 4.12.0 (KitKat)
Assignee: Jonathan Pryor
URL:
Depends on:
Blocks:
 
Reported: 2013-10-31 16:12 UTC by Jon Goldberger [MSFT]
Modified: 2014-03-26 03:06 UTC (History)
3 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Test Case (21.49 KB, application/zip)
2013-10-31 16:12 UTC, Jon Goldberger [MSFT]
Details
Call stack (7.35 KB, text/plain)
2013-10-31 16:19 UTC, Jon Goldberger [MSFT]
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
VERIFIED FIXED

Comment 1 Jon Goldberger [MSFT] 2013-10-31 16:13:30 UTC
I've ran into problems trying out async support in Xamarin.Android. My app
tries to perform a POST request with cancellation support. When I try to
cancel ongoing async HttpClient call, it either works as intended (cancels,
throws OperationCanceledException at the await site), or throws
TargetInvocationException with InnerException being NullReferenceException
thrown in Mono internals. If I catch that TargetInvocationException,
anything goes afterwards -further async calls may hang, or the finally
blocks in async methods don't run, or everything seems to work fine. GETs
work and so do non-HTTPS POSTs. I've reproduced this behavior on 4.8.3 and
4.10 alpha, and on real devices and on the emulator.



I'm attaching a repro solution (just tap the first button and then quickly
the second one). In case you can't reproduce it yourself, I'm also attaching
a .ToString of the TargetInvocationException in question.
Comment 2 Jon Goldberger [MSFT] 2013-10-31 16:19:03 UTC
Created attachment 5297 [details]
Call stack
Comment 3 Jonathan Pryor 2013-11-01 16:35:33 UTC
The apparent problem is that WebConnection.nstream is null when we attempt to access it:

https://github.com/mono/mono/blob/8f026e3e/mcs/class/System/System.Net/WebConnection.cs#L1170

    if ((bool) piTrustFailure.GetValue (nstream, null)) {

if `nstream` is null, you'll get a NullReferenceException wrapped in a TargetInvocationException, which is exactly what you're seeing.

Why is `nstream` null? Additional investigation results in: https://gist.github.com/jonpryor/4161cf3b927ada7d2756

> # WebConnection.CreateStream; from 5 Threadpool worker
> # WebConnection.Write; from 5 Threadpool worker
> # WebConnection.Close; from 1  at    at System.Environment.get_StackTrace()
>    at System.Net.WebConnection.Close(Boolean sendNext)
>    at System.Net.WebConnection.Abort(System.Object sender, System.EventArgs args)
>    at System.Net.WebConnection+AbortHelper.Abort(System.Object sender, System.EventArgs args)
>    at System.Net.HttpWebRequest.Abort()
...
>    at HttpClientAsyncCancellationRepro.Activity1.CancelButton_Click(System.Object sender, System.EventArgs e)
>    at System.Object.e7b5b870-ea0f-434f-bc31-984f665a44ad(IntPtr , IntPtr , IntPtr )
> # WebConnection.Write: checking piTrustFailure; from 5 Threadpool worker

So what's happening is that AccessGoogleButton_Click() causes a ThreadPool worker thread to start the HTTPS request. Meanwhile, the user clicks the Cancel button, causing _cancellationTokenSource.Cancel() to be invoked from the main thread, which causes the request to be Aborted(), due to the CancalleationToken.Register() call at: 

https://github.com/mono/mono/blob/8f026e3e/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs#L316

HttpClient.Abort() calls WebConnection.Close(), which nulls out WebConnection.nstream, resulting in the in-flight WebConnection.Write() call to NRE because nstream was changed from another thread.
Comment 4 Jonathan Pryor 2013-11-01 16:57:59 UTC
Fixed in mono/55f400b6:

https://github.com/mono/mono/commit/55f400b6446024adef5dcc8cc690b6951af98125

This will be integrated in a future Xamarin.Android release.
Comment 5 Sadik Ali 2014-03-26 03:06:19 UTC
I have verified this issue and noticed that issue resolved. I followed below steps:

1. Open attached project on XS.
2. Debug application on emulator and devices.
3. Click on "Access Google through HTTPS" buton.
4. Click on "Cancle" button.
5. Repeated steps 3 and 4

Refer scree cast: http://www.screencast.com/t/o0GIqZNEX

Environment Info: 

=== Xamarin Studio ===
Version 4.2.4 (build 32)
Installation UUID: 6ea47b0d-1852-4aaf-808d-373ff0a5002b
Runtime:
 Mono 3.2.7 ((no/40f92d5)
 GTK+ 2.24.23 (Raleigh theme)

 Package version: 302070000

=== Xamarin.Android ===
Version: 4.12.3 (Trial Edition)
Android SDK: /Users/jatin66/Desktop/Backup/android-sdk-macosx
 Supported Android versions:
  1.6   (API level 4)
  2.2   (API level 8)
  2.3   (API level 10)
  3.1   (API level 12)
  3.2   (API level 13)
  4.0   (API level 14)
  4.0.3 (API level 15)
  4.1   (API level 16)
  4.2   (API level 17)
  4.3   (API level 18)
  4.4   (API level 19)
Java SDK: /usr
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)

=== Apple Developer Tools ===
Xcode 4.6.3 (2068)
Build 4H1503

=== Xamarin.Mac ===
Xamarin.Mac: 1.6.27

=== Xamarin.iOS ===
Version: 7.2.1.25 (Trial Edition)

=== Build Information ===
Release ID: 402040032
Git revision: a160c35dac9ab9fd32eeadaa171216316d5a5133
Xamarin addins: a779416ceabd54981ce812771a4061c942e8b872

=== Operating System ===
Mac OS X 10.7.5
Darwin Jatin66s-iMac.local 11.4.2 Darwin Kernel Version 11.4.2
    Thu Aug 23 16:25:48 PDT 2012
    root:xnu-1699.32.7~1/RELEASE_X86_64 x86_64