Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reusing SocketAsyncEventArgs for multiple calls to the static Socket.Connect() #8871

Open
baulig opened this issue May 25, 2018 · 4 comments

Comments

@baulig
Copy link
Contributor

baulig commented May 25, 2018

Using the static Socket.Connect() multiple times with the same SocketAsyncEventArgs throws

  at System.Net.Sockets.SocketAsyncEventArgs.SetLastOperation (System.Net.Sockets.SocketAsyncOperation op) [0x00033] in /Workspace/mono-master/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs:196 
  at System.Net.Sockets.SocketAsyncEventArgs.StartOperationWrapperConnect (System.Net.Sockets.MultipleConnectAsync args) [0x00000] in /Workspace/mono-master/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs:245 
  at System.Net.Sockets.Socket.ConnectAsync (System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType, System.Net.Sockets.SocketAsyncEventArgs e) [0x0007f] in /Workspace/mono-master/mcs/class/referencesource/System/net/System/Net/Sockets/Socket.cs:7877 
  at X.TestStaticConnect (System.Net.Sockets.SocketAsyncEventArgs e, System.String host, System.Int32 port) [0x00067] in <a3d5ba1db6c141f58c821248794a8daa>:0 
  at X.TestMultipleConnect (System.Boolean reuse) [0x00124] in <a3d5ba1db6c141f58c821248794a8daa>:0 
   --- End of inner exception stack trace ---

Simple example:

	static async Task TestMultipleConnect (bool reuse)
	{
		var port = 8888;
		var socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
		socket.Bind (new IPEndPoint (IPAddress.Loopback, port));
		socket.Listen (3);

		ThreadPool.QueueUserWorkItem (_ => {
			var accepted = socket.Accept ();
			Console.WriteLine ($"ACCEPTED: {accepted.RemoteEndPoint}");

			accepted.Close ();

			var accepted2 = socket.Accept ();
			Console.WriteLine ($"ACCEPTED #1: {accepted2.RemoteEndPoint}");
		});

		var e = new SocketAsyncEventArgs ();
		await TestStaticConnect (e, "localhost", port).ConfigureAwait (false);
		Console.WriteLine ($"FIRST DONE!");

		if (!reuse)
			e = new SocketAsyncEventArgs ();

		await TestStaticConnect (e, "localhost", port).ConfigureAwait (false);
		Console.WriteLine ($"SECOND DONE!");
	}

	static Task TestStaticConnect (SocketAsyncEventArgs e, string host, int port)
	{
		var tcs = new TaskCompletionSource<object> ();

		e.Completed += (object sender, SocketAsyncEventArgs inner) => {
			Console.Error.WriteLine ($"COMPLETED: {inner.SocketError}");
			tcs.TrySetResult (null);
		};
		e.RemoteEndPoint = IPAddress.TryParse (host, out IPAddress address) ?
			(EndPoint)new IPEndPoint (address, port) :
			new DnsEndPoint ("localhost", port);
		Console.Error.WriteLine (e.RemoteEndPoint.AddressFamily);

		var ret = Socket.ConnectAsync (SocketType.Stream, ProtocolType.Tcp, e);
		Console.Error.WriteLine (ret);

		return tcs.Task;
	}

This works fine on .NET.

Full test case:
A.cs

This is a problem because the new System.Net.Http code from CoreFX is reusing SocketAsyncEventArgs instances.

@baulig
Copy link
Contributor Author

baulig commented May 25, 2018

You may have to run this on a Mac where localhost resolves to both ::1 and 127.0.0.1, with the IPv6 address being returned first - which seems to be the default these days.

@baulig
Copy link
Contributor Author

baulig commented May 25, 2018

There's another problem when using DnsEndPoint with socket.BeginConnect: see this new test.

1) Xamarin.WebTests.Console.Tests.SocketTests.BeginEndAsync.Run(True): Error

System.NotImplementedException: This method is not implemented by this class.
  at System.Net.EndPoint.Serialize () [0x00000] in /Workspace/mono-test/mcs/class/referencesource/System/net/System/Net/EndPoint.cs:40 
  at System.Net.Sockets.Socket.BeginSConnect (System.Net.Sockets.SocketAsyncResult sockares) [0x000ee] in /Workspace/mono-test/mcs/class/System/System.Net.Sockets/Socket.cs:1065 
  at System.Net.Sockets.Socket.BeginConnect (System.Net.EndPoint remoteEP, System.AsyncCallback callback, System.Object state) [0x00032] in /Workspace/mono-test/mcs/class/System/System.Net.Sockets/Socket.cs:986 
  at Xamarin.WebTests.SocketTests.BeginEndAsync.StartClient (Xamarin.AsyncTests.TestContext ctx, System.Net.EndPoint endPoint, System.Threading.CancellationToken cancellationToken) [0x0002d] in /Workspace/web-tests/Xamarin.WebTests.Tests/Xamarin.WebTests.SocketTests/BeginEndAsync.cs:90 
  at Xamarin.WebTests.SocketTests.SocketTestFixture+SocketConnection.Start (Xamarin.AsyncTests.TestContext ctx, Xamarin.WebTests.ConnectionFramework.IConnectionInstrumentation instrumentation, System.Threading.CancellationToken cancellationToken) [0x00086] in /Workspace/web-tests/Xamarin.WebTests.Tests/Xamarin.WebTests.SocketTests/SocketTestFixture.cs:168 
  at Xamarin.WebTests.TestRunners.ConnectionTestRunner.StartClient (Xamarin.AsyncTests.TestContext ctx, System.Threading.CancellationToken cancellationToken) [0x00001] in /Workspace/web-tests/Xamarin.WebTests.Framework/Xamarin.WebTests.TestRunners/ConnectionTestRunner.cs:87 
  at Xamarin.WebTests.ConnectionFramework.ClientAndServer.Initialize (Xamarin.AsyncTests.TestContext ctx, System.Threading.CancellationToken cancellationToken) [0x00103] in /Workspace/web-tests/Xamarin.WebTests.Framework/Xamarin.WebTests.ConnectionFramework/ClientAndServer.cs:108 
  at Xamarin.AsyncTests.Framework.Reflection.ReflectionFixtureInstance.Initialize (Xamarin.AsyncTests.TestContext ctx, System.Threading.CancellationToken cancellationToken) [0x0004c] in /Workspace/web-tests/Xamarin.AsyncTests.Framework/Xamarin.AsyncTests.Framework.Reflection/ReflectionFixtureInstance.cs:60 
  at Xamarin.AsyncTests.Framework.HeavyTestInvoker.SetUp (Xamarin.AsyncTests.TestContext ctx, Xamarin.AsyncTests.Framework.TestInstance instance, System.Threading.CancellationToken cancellationToken) [0x000e9] in /Workspace/web-tests/Xamarin.AsyncTests.Framework/Xamarin.AsyncTests.Framework/HeavyTestInvoker.cs:69 

@baulig
Copy link
Contributor Author

baulig commented May 25, 2018

Added some more tests to web-tests/Xamarin.WebTests.SocketTests.

@baulig
Copy link
Contributor Author

baulig commented May 29, 2018

Unfortunately, that doesn't fix the problem.

@baulig baulig reopened this May 29, 2018
baulig pushed a commit to baulig/mono that referenced this issue May 29, 2018
baulig pushed a commit to baulig/mono that referenced this issue May 29, 2018
monojenkins pushed a commit to monojenkins/mono that referenced this issue Jun 13, 2018
monojenkins pushed a commit to monojenkins/mono that referenced this issue Jun 13, 2018
UnityAlex pushed a commit to Unity-Technologies/mono that referenced this issue Sep 3, 2019
UnityAlex pushed a commit to Unity-Technologies/mono that referenced this issue Sep 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants