Bug 2309 - Transient webexception when calling WebClient.OpenRead()
Summary: Transient webexception when calling WebClient.OpenRead()
Status: RESOLVED INVALID
Alias: None
Product: Class Libraries
Classification: Mono
Component: System ()
Version: 2.10.x
Hardware: PC Windows
: --- normal
Target Milestone: Untriaged
Assignee: Gonzalo Paniagua Javier
URL:
Depends on:
Blocks:
 
Reported: 2011-12-02 07:02 UTC by Bas Smit
Modified: 2015-05-18 12:55 UTC (History)
6 users (show)

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

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 GitHub or Developer Community 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:
RESOLVED INVALID

Description Bas Smit 2011-12-02 07:02:11 UTC
Description of Problem:

When I run the program below every so often I get the exception below. I have never encountered the exception running the program in .net. I get the exception running 2.10.6 on Windows7. I do not get the exception running 2.10.6 on OSX 10.6.7 (win and osx are running on the same hardware).


Steps to reproduce the problem:

1. Compile attached program.
2. Run on windows7 and wait for exception to occur


Actual Results:

Unhandled Exception: System.Net.WebException: Error getting response stream (ReadDone1): ReceiveFailure ---> System.IO.IOException: EndRead failure ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host.

  at System.Net.Sockets.Socket.EndReceive (IAsyncResult result) [0x00000] in <filename unknown>:0
  at System.Net.Sockets.NetworkStream.EndRead (IAsyncResult ar) [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Net.Sockets.NetworkStream.EndRead (IAsyncResult ar) [0x00000] in <filename unknown>:0
  at System.Net.WebConnection.ReadDone (IAsyncResult result) [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0
  at System.Net.HttpWebRequest.GetResponse () [0x00000] in <filename unknown>:0
  at System.Net.WebClient.GetWebResponse (System.Net.WebRequest request) [0x00000] in <filename unknown>:0
  at System.Net.WebClient.OpenRead (System.Uri address) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.Net.WebException: Error getting response stream (ReadDone1): Receive
Failure ---> System.IO.IOException: EndRead failure ---> System.Net.Sockets.SocketException: An existing conne
ction was forcibly closed by the remote host.

  at System.Net.Sockets.Socket.EndReceive (IAsyncResult result) [0x00000] in <filename unknown>:0
  at System.Net.Sockets.NetworkStream.EndRead (IAsyncResult ar) [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Net.Sockets.NetworkStream.EndRead (IAsyncResult ar) [0x00000] in <filename unknown>:0
  at System.Net.WebConnection.ReadDone (IAsyncResult result) [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0
  at System.Net.HttpWebRequest.GetResponse () [0x00000] in <filename unknown>:0
  at System.Net.WebClient.GetWebResponse (System.Net.WebRequest request) [0x00000] in <filename unknown>:0
  at System.Net.WebClient.OpenRead (System.Uri address) [0x00000] in <filename unknown>:0

Expected Results:

Successful connection


How often does this happen? 

Once in 10.000 times


Additional Information:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;

static class Program
{
	static void Main()
	{
		int i = 0;

		while (true)
		{
			var tcp = new TcpListener(IPAddress.Loopback, 0);
			tcp.Start();
			tcp.BeginAcceptTcpClient(Accept, tcp);
			const string url = "http://url.com/a.html";
			var proxy = new WebProxy("127.0.0.1", ((IPEndPoint)tcp.LocalEndpoint).Port);
			var wc = new WebClient { Proxy = proxy };
			wc.OpenRead(url);

			// Exception always occurs in second OpenRead().
			// Without this line the exception does not occur.
			wc.OpenRead(url);

			lock (tcp)
				tcp.Stop();

			Console.WriteLine(i++);
		}
	}

	static void Accept(IAsyncResult iar)
	{
		lock (iar.AsyncState)
		{
			var tcp = (TcpListener)iar.AsyncState;

			if (!tcp.Server.IsBound)
				return;

			tcp.BeginAcceptTcpClient(Accept, tcp);

			using (var c = tcp.EndAcceptTcpClient(iar))
			using (var s = c.GetStream())
			using (var sr = new StreamReader(s))
			using (var sw = new StreamWriter(s))
			{
				// Similar exception occurs every time
				// without calling ReadLine() at least once
				sr.ReadLine();
				
				const string content = "bla";
				sw.WriteLine("HTTP/1.1 200 OK");
				sw.WriteLine("CONTENT-LENGTH: " + content.Length);
				sw.WriteLine();
				sw.Write(content);
				sw.Flush();
			}
		}
	}
}
Comment 1 Bas Smit 2011-12-02 08:07:53 UTC
fwiw I forgot to put WebClient wc in a using block, however this does not fix the problem, nor does creating a new WebProxy and WebClient for each call to OpenRead()
Comment 2 Gonzalo Paniagua Javier 2012-01-10 17:11:13 UTC
I have not tried to run the test, but I can see one problem: you call BeginAcceptTcpClient() before EndAcceptTcpClient().

And then, the main problem is that the TcpClient accepted in Accept(), along with the stream and StreamReader/Writer are at some point disposed because there are no references to them. That causes the socket to close and produce the error.
Comment 3 Bas Smit 2012-01-11 05:50:23 UTC
That may be, however the error does occur in .net (of course I can not prove a negative, but i have never seen it). It is obviously not my decision, but it seems to me mono should be able to run all code that can be run in .net. Anyway thanks for the reply, I will see if I can prevent the error from occurring with your suggestions.
Comment 4 Bas Smit 2012-01-11 05:51:11 UTC
Blegh, I obviously meant to say that the error does _not_ occur in .net
Comment 5 Gonzalo Paniagua Javier 2012-01-11 10:53:39 UTC
The GC moves in misterious ways. Perhaps if you explicitly call GC.Collect() you will see the error more often in ms.net.
Comment 6 Bas Smit 2012-01-23 17:30:02 UTC
I tried your suggestion of moving BeginAcceptTcpClient below EndAcceptTcpClient, but the result is the same. I rewrote the code to use the synchronous method AcceptTcpClient, but the program still crashes. Below you will find the synchronous version of the program. Below that I added some stacktraces from running the program on my mac (osx 10.6.7, mono 2.10.6). (The first version of the program bumped into other problems on the mac that hid the crash, the new program brings out a couple of different exceptions)


Simplified program:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

static class Program
{
	static void Main()
	{
		var server = new Server();
		const string url = "http://url.com";
		int i = 0;

		using (var webClient = server.GetWebClient())
		{
			while (true)
			{
				webClient.OpenRead(url).Dispose();
				Console.WriteLine(i++);
			}
		}
	}
}

class Server
{
	readonly TcpListener tcp;

	public Server()
	{
		tcp = new TcpListener(IPAddress.Loopback, 0);
		tcp.Start();
		new Thread(Accept).Start();
	}

	public WebClient GetWebClient()
	{
		var endpoint = (IPEndPoint)tcp.LocalEndpoint;
		var proxy = new WebProxy(endpoint.Address.ToString(), endpoint.Port);
		return new WebClient { Proxy = proxy };
	}

	void Accept()
	{
		while (true)
		{
			using (var c = tcp.AcceptTcpClient())
			using (var s = c.GetStream())
			using (var sr = new StreamReader(s))
			using (var sw = new StreamWriter(s))
			{
				sr.ReadLine();
				const string content = "bla";
				sw.WriteLine("HTTP/1.1 200 OK");
				sw.WriteLine("CONTENT-LENGTH: " + content.Length);
				sw.WriteLine();
				sw.Write(content);
				sw.Flush();
			}
		}
	}
}



Mac Stacktraces:

Unhandled Exception: System.Net.WebException: Error getting response stream (ReadDone1): ReceiveFailure ---> System.IO.IOException: EndRead failure ---> System.Net.Sockets.SocketException: Connection reset by peer
  at System.Net.Sockets.Socket.EndReceive (IAsyncResult result) [0x00000] in <filename unknown>:0 
  at System.Net.Sockets.NetworkStream.EndRead (IAsyncResult ar) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Net.Sockets.NetworkStream.EndRead (IAsyncResult ar) [0x00000] in <filename unknown>:0 
  at System.Net.WebConnection.ReadDone (IAsyncResult result) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
  at System.Net.HttpWebRequest.GetResponse () [0x00000] in <filename unknown>:0 
  at System.Net.WebClient.GetWebResponse (System.Net.WebRequest request) [0x00000] in <filename unknown>:0 
  at System.Net.WebClient.OpenRead (System.Uri address) [0x00000] in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.Net.WebException: Error getting response stream (ReadDone1): ReceiveFailure ---> System.IO.IOException: EndRead failure ---> System.Net.Sockets.SocketException: Connection reset by peer
  at System.Net.Sockets.Socket.EndReceive (IAsyncResult result) [0x00000] in <filename unknown>:0 
  at System.Net.Sockets.NetworkStream.EndRead (IAsyncResult ar) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Net.Sockets.NetworkStream.EndRead (IAsyncResult ar) [0x00000] in <filename unknown>:0 
  at System.Net.WebConnection.ReadDone (IAsyncResult result) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
  at System.Net.HttpWebRequest.GetResponse () [0x00000] in <filename unknown>:0 
  at System.Net.WebClient.GetWebResponse (System.Net.WebRequest request) [0x00000] in <filename unknown>:0 
  at System.Net.WebClient.OpenRead (System.Uri address) [0x00000] in <filename unknown>:0 


Unhandled Exception: System.Net.WebException: Error getting response stream (ReadDone2): ReceiveFailure ---> System.Exception:    at System.Net.WebConnection.HandleError(WebExceptionStatus st, System.Exception e, System.String where)
   at System.Net.WebConnection.ReadDone(IAsyncResult result)
  at System.Net.WebConnection.HandleError (WebExceptionStatus st, System.Exception e, System.String where) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
  at System.Net.HttpWebRequest.GetResponse () [0x00000] in <filename unknown>:0 
  at System.Net.WebClient.GetWebResponse (System.Net.WebRequest request) [0x00000] in <filename unknown>:0 
  at System.Net.WebClient.OpenRead (System.Uri address) [0x00000] in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.Net.WebException: Error getting response stream (ReadDone2): ReceiveFailure ---> System.Exception:    at System.Net.WebConnection.HandleError(WebExceptionStatus st, System.Exception e, System.String where)
   at System.Net.WebConnection.ReadDone(IAsyncResult result)
  at System.Net.WebConnection.HandleError (WebExceptionStatus st, System.Exception e, System.String where) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
  at System.Net.HttpWebRequest.GetResponse () [0x00000] in <filename unknown>:0 
  at System.Net.WebClient.GetWebResponse (System.Net.WebRequest request) [0x00000] in <filename unknown>:0 
  at System.Net.WebClient.OpenRead (System.Uri address) [0x00000] in <filename unknown>:0
Comment 7 Nicholas Ventimiglia 2015-05-18 12:55:51 UTC
I ran into this issue when using System.Net.WebSockets.ClientWebSocket on the Xamarin.Android platform. The error occured when I was testing some reconnection logic (connect, pull internet, reconnect, fail, plug internet in, connect, ect). My stack trace is below.

System.Net.WebSockets.WebSocketException: Generic WebSocket exception ---> System.Exception: Error getting response stream (ReadDone2): ReceiveFailure ---> System.Exception:    at System.Net.WebConnection.HandleError(WebExceptionStatus st, System.Exception e, System.String where)
   at System.Net.WebConnection.ReadDone(IAsyncResult result)
  at System.Net.WebConnection.HandleError (WebExceptionStatus st, System.Exception e, System.String where) [0x00044] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00064] in <filename unknown>:0
  at System.Threading.Tasks.TaskFactory`1[System.Net.WebResponse].FromAsyncCoreLogic (IAsyncResult iar, System.Func`2 endFunction, System.Action`1 endAction, System.Threading.Tasks.Task`1 promise, Boolean requiresSynchronization) [0x00014] in <filename unknown>:0
  at --- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000b] in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0004e] in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in <filename unknown>:0
  at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[System.Net.WebResponse].GetResult () [0x00000] in <filename unknown>:0
  at System.Net.WebSockets.ClientWebSocket+<ConnectAsync>c__async0.MoveNext () [0x003d6] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Net.WebSockets.ClientWebSocket+<ConnectAsync>c__async0.MoveNext () [0x00412] in <filename unknown>:0
  at --- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000b] in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0004e] in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in <filename unknown>:0
  at RealtimeFramework.Messaging.Droid.WebSocketWrapper+<ConnectAsync>d__9.MoveNext () [0x0008d] in <filename unknown>:0
  at --- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000b] in <filename unknown>:0
  at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>m__1 (System.Object state) [0x00000] in <filename unknown>:0

My code is below.

private async void ConnectAsync(Uri uri)
        {
			await Client.ConnectAsync(uri, _cancellationToken);
            CallOnConnected();
            StartListen();
        }

        private async void StartListen()
        {
            var buffer = new byte[ReceiveChunkSize];

            try
            {
                while (Client.State == WebSocketState.Open)
                {
                    var stringResult = new StringBuilder();


                    WebSocketReceiveResult result;
                    do
                    {
                        result = await Client.ReceiveAsync(new ArraySegment<byte>(buffer), _cancellationToken);

                        if (result.MessageType == WebSocketMessageType.Close)
                        {
							await Client.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
							Client.Dispose ();
                        }
                        else
                        {
                            var str = Encoding.UTF8.GetString(buffer, 0, result.Count);
                            stringResult.Append(str);
                        }

                    } while (!result.EndOfMessage);

                    CallOnMessage(stringResult);
                }
            }
            catch (Exception)
            {
                CallOnDisconnected();
			}finally{
				Client.Dispose ();
			}
        }