Created attachment 21864 [details]
Sample project. Use with slow network, tap button and watch output window.
This does seem very similar to https://bugzilla.xamarin.com/show_bug.cgi?id=51423 , however I have tested with the latest Stable and Alpha as of 4/27/17 and it still reproduces. Also, in this case we're explicitly cancelling rather than disconnecting the network.
When calling HttpClient.SendAsync with a CancellationToken, cancelling that token after a certain time "causes no response and HttpClient will hang indefinitely (no exception or response back)" (quoted from the other bug because the resulting symptom is the same).
Still observed with this Alpha build, suggesting that the fix for the other bug did not fix this:
Version: 10.10.0.21 (Visual Studio Enterprise)
Build date: 2017-04-22 14:32:46-0400
Sample project attached. Uses CancelAfter to simulate a user canceling the request after a certain time while the request is in-progress. Use "Network Link Conditioner" or a proxy (e.g. Fiddler) to simulate slow network so that there is time for the cancellation to occur, then tap the Button and watch the debugger output.
(there is only a single function of interest in the ViewController of the project... probably could have done this as a unit test project or Workbook, but this seems more useful for debugging?)
This has only been seen with the current Xamarin NSUrlSessionHandler.
- The Managed handler cancels exactly as expected.
- CFNetwork "stops" when canceled but reports success? (I didn't look further into that, maybe examining the response object makes clear that it was canceled?)
- ModernHttpClient simply ignores cancellation attempts (not sure if that's better or worse....)
I believe that this specifically happens if the token is canceled while the response content is being read (via HttpClient.SendAsyncWorker's call to LoadIntoBufferAsync if the HttpCompletionOption is ResponseContentRead). Note however that I have not actually debugged into HttpClient or NSUrlSessionHandler. I believe that LoadIntoBufferAsync is related because I am unable to reproduce the hang if the token is canceled very quickly or if HttpCompletionOption is ResponseHeadersRead. (also this explains the ModernHttpClient behavior, as that simply passes CancellationToken.None into its Content)
(I tried using ResponseHeadersRead and calling LoadIntoBufferAsync separately to isolate the issue, however that winds up ignoring cancellation because HttpClient wraps the provided CancellationToken in a LinkedTokenSource which it declares in a "using" within SendAsyncWorker, so after SendAsync returns the original CancellationToken is no longer attached to the Content because the LinkedTokenSource was disposed...)
I have been working lately in the HttpClient issues, let me take a look and I will get back to you as soon as possible. I'll test all of the handlers to make sure that we do have the expected behaviour which AFAIK should be the same as the one exposed by the "Managed" implementation.