Ensure that when an async read is performed on a response content the
authorManuel de la Pena <mandel@microsoft.com>
Mon, 24 Apr 2017 11:22:05 +0000 (13:22 +0200)
committerMarek Safar <marek.safar@gmail.com>
Wed, 26 Apr 2017 12:46:37 +0000 (14:46 +0200)
errors are correctly dealt with.

Some network errors in iOS are exposed as Stream errors, specially those
related with the lost of the connection. This patch ensures that if such
an issue happens an exception is raised in the async read task.

Fixes bug https://bugzilla.xamarin.com/show_bug.cgi?id=53792

mcs/class/System.Net.Http/CFContentStream.cs

index 270846cb6b7012b11d5dc5e3d865269fd8cd51d3..d639ae2a29f71523832502a69bc9b6c0ee4c5b51 100644 (file)
@@ -33,10 +33,13 @@ using System.Net;
 
 #if XAMCORE_4_0
 using CFNetwork;
+using CoreFoundation;
 #elif XAMCORE_2_0
 using CoreServices;
+using CoreFoundation;
 #else
 using MonoTouch.CoreServices;
+using MonoTouch.CoreFoundation;
 #endif
 
 namespace System.Net.Http
@@ -54,6 +57,7 @@ namespace System.Net.Http
                Mutex data_mutex;
                AutoResetEvent data_event;
                AutoResetEvent data_read_event;
+               Exception http_exception = null;
 
                // The requirements are:
                // * We must read at least one byte from the stream every time
@@ -77,6 +81,7 @@ namespace System.Net.Http
                public CFContentStream (CFHTTPStream stream)
                {
                        this.http_stream = stream;
+                       this.http_stream.ErrorEvent += HandleErrorEvent;
                        data = new BufferData () {
                                Buffer = new byte [4096],
                        };
@@ -85,6 +90,17 @@ namespace System.Net.Http
                        data_mutex = new Mutex ();
                }
 
+               void HandleErrorEvent (object sender, CFStream.StreamEventArgs e)
+               {
+                       var gotMutex = data_mutex.WaitOne ();
+                       if (gotMutex) {
+                               var stream = (CFHTTPStream)sender;
+                               if (e.EventType == CFStreamEventType.ErrorOccurred)
+                                       http_exception = stream.GetError ();
+                               data_mutex.ReleaseMutex ();
+                       }
+               }
+
                public void ReadStreamData ()
                {
                        data_read_event.WaitOne (); // make sure there's no pending data.
@@ -111,6 +127,10 @@ namespace System.Net.Http
                {
                        while (data_event.WaitOne ()) {
                                data_mutex.WaitOne ();
+                               if (http_exception != null) {
+                                       data_mutex.ReleaseMutex ();
+                                       throw http_exception;
+                               }
                                if (data == null || data.Length <= 0) {
                                        data_mutex.ReleaseMutex ();
                                        data_read_event.Set ();