[System] Fix RequestCanceled ex on ResponseStream.Close
authorMarcos Henrich <marcos.henrich@xamarin.com>
Wed, 20 Jul 2016 16:11:30 +0000 (17:11 +0100)
committerMarcos Henrich <marcos.henrich@xamarin.com>
Wed, 20 Jul 2016 17:31:32 +0000 (18:31 +0100)
Fixes issues where ResponseStream.Close would throw an exception when
peer had already closed the connection and ResponseStream.Close would
still try to communicating to peer that it was closing.

The issue was brought to our attention by failures on:
  - MonoTests.System.Net.WebRequestTest.TestReceiveCancelation
  - MonoTests.System.Net.HttpWebRequestTest.TestLargeDataReading

mcs/class/System/System.Net/ResponseStream.cs

index 860509b9aceaa2776fb0bb105699e7a0d6fa528e..6a47f40ae2a3cf823bfda8923e86cb2a7334e2f1 100644 (file)
@@ -81,19 +81,25 @@ namespace System.Net {
                                byte [] bytes = null;
                                MemoryStream ms = GetHeaders (true);
                                bool chunked = response.SendChunked;
-                               if (ms != null) {
-                                       long start = ms.Position;
-                                       if (chunked && !trailer_sent) {
-                                               bytes = GetChunkSizeBytes (0, true);
-                                               ms.Position = ms.Length;
-                                               ms.Write (bytes, 0, bytes.Length);
+                               if (stream.CanWrite) {
+                                       try {
+                                               if (ms != null) {
+                                                       long start = ms.Position;
+                                                       if (chunked && !trailer_sent) {
+                                                               bytes = GetChunkSizeBytes (0, true);
+                                                               ms.Position = ms.Length;
+                                                               ms.Write (bytes, 0, bytes.Length);
+                                                       }
+                                                       InternalWrite (ms.GetBuffer (), (int) start, (int) (ms.Length - start));
+                                                       trailer_sent = true;
+                                               } else if (chunked && !trailer_sent) {
+                                                       bytes = GetChunkSizeBytes (0, true);
+                                                       InternalWrite (bytes, 0, bytes.Length);
+                                                       trailer_sent = true;
+                                               }
+                                       } catch (IOException ex) {
+                                               // Ignore error due to connection reset by peer
                                        }
-                                       InternalWrite (ms.GetBuffer (), (int) start, (int) (ms.Length - start));
-                                       trailer_sent = true;
-                               } else if (chunked && !trailer_sent) {
-                                       bytes = GetChunkSizeBytes (0, true);
-                                       InternalWrite (bytes, 0, bytes.Length);
-                                       trailer_sent = true;
                                }
                                response.Close ();
                        }