Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs - #787

Merged
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync
Apr 27, 2020
Merged

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs#787
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync

Conversation

@tmds

@tmdstmds commented Dec 12, 2019

Copy link
Copy Markdown
Member

No description provided.

@tmds
tmds marked this pull request as ready for review December 12, 2019 09:03
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl @stephentoub this PR is not finished but I'd like some early feedback.
And, some of the test failures I get don't make sense to me (yet).

It seems github doesn't allow me to mark this as Draft and still do a CI run. Can you please mark this as no-merge?

@tmdstmds changed the title Refactor Task SocketAsync.ConnectAsync methods to use AwaitableSocketAsyncEventArgsRefactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgsDec 12, 2019
@tmds
tmdsforce-pushed the socket_connectasync branch from 749388f to ffcc63aCompareDecember 12, 2019 09:07
@MihaZupanMihaZupan added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Dec 12, 2019
@stephentoub

Copy link
Copy Markdown
Member

Thanks, @tmds. I'm concerned about doing something like this until https://github.com/dotnet/corefx/issues/39466 is addressed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@stephentoub

Copy link
Copy Markdown
Member

I'm concerned about doing something like this until dotnet/corefx#39466 is addressed.

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Comment threadsrc/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs Outdated
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Yes, it's on the Socket where it was used to Connect, so not keeping another Socket alive.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@scalablecory
scalablecory requested a review from a teamDecember 15, 2019 01:05
@stephentoubstephentoub removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jan 6, 2020
@stephentoub

Copy link
Copy Markdown
Member

@tmds, some of these test failures look relevant.

@tmds

tmds commented Jan 15, 2020

Copy link
Copy Markdown
MemberAuthor

This test is now failing on Windows:

[Fact]publicasyncTaskCtor_NotStream_ThrowsIOException(){using(Socketlistener=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp))using(Socketclient=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp)){listener.Bind(newIPEndPoint(IPAddress.Loopback,0));awaitclient.ConnectAsync(newIPEndPoint(IPAddress.Loopback,((IPEndPoint)listener.LocalEndPoint).Port));Assert.Throws<IOException>(()=>newNetworkStream(client));}}

Instead of throwing at the expected location, it's throwing on the ConnectAsync call above:

System.Net.Sockets.SocketException : An invalid argument was supplied.
 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/

I'm missing the fallback for connectionless protocols that is part of BeginConnect:

internalIAsyncResultUnsafeBeginConnect(EndPointremoteEP,AsyncCallbackcallback,objectstate,boolflowContext=false)
{
if(CanUseConnectEx(remoteEP))
{
returnBeginConnectEx(remoteEP,flowContext,callback,state);
}
EndPointendPointSnapshot=remoteEP;
varasyncResult=newConnectAsyncResult(this,endPointSnapshot,state,callback);
// For connectionless protocols, Connect is not an I/O call.
Connect(remoteEP);
asyncResult.FinishPostingAsyncOp();
// Synchronously complete the I/O and call the user's callback.
asyncResult.InvokeCallback();
returnasyncResult;
}

I'll add this and check if there are other things which may be missing.

@stephentoub

Copy link
Copy Markdown
Member

Thanks.

@tmds
tmdsforce-pushed the socket_connectasync branch from 4745f62 to 6404854CompareJanuary 30, 2020 13:57
@tmds

tmds commented Feb 10, 2020

Copy link
Copy Markdown
MemberAuthor

The latest change was to change ConnectAsync(SocketAsyncEventArgs) to make it work for UDP sockets. On Windows, the implementation was calling ConnectEx, but that isn't UDP compatible, so WSAConnect is now called instead:

if(CanUseConnectEx(endPointSnapshot)){socketError=e.DoOperationConnectEx(this,_handle);}else{// For connectionless protocols, Connect is not an I/O call.socketError=e.DoOperationConnect(this,_handle);}

I'm not sure if all parts of the CanUseConnectEx check apply here,. It does put us on the WSAConnect way, since the error message has changed:

System.Net.Sockets.SocketException : A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

with stacktrace

 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs:line 400
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/C

From the error message I'd guess WSAENOTCONN is returned by WSAConnect, but that doesn't show up on the WSAConnect doc page. I'm lost.

I don't have a Windows machine to debug.
@dotnet/ncl can someone help me make this work on Windows?

@tmds

tmds commented Feb 11, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@karelz can someone help me with this?

@tmds

tmds commented Feb 27, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@antonfirsov maybe you can have a look?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds your assumption was correct, CanUseConnectEx(...) does not return the right result on SocketAsyncEventArgs path, therefore ConnectEx is being called instead of WSAConnect.

This is even worse on master, since the original SocketAsyncEventArgs code path doesn't even try to check if it can use ConnectEx. The following code fails, which is a bug:

stringpath=Path.Combine(Path.GetTempPath(),Path.GetRandomFileName());varendPoint=newUnixDomainSocketEndPoint(path);usingvarserver=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);usingvarclient=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);server.Bind(endPoint);server.Listen(1);usingvarmre=newManualResetEventSlim(false);usingvarsea=newSocketAsyncEventArgs(){RemoteEndPoint=endPoint};sea.Completed+=(_,__)=>mre.Set();if(client.ConnectAsync(sea))mre.Wait();Assert.Equal(SocketError.Success,sea.SocketError);

@stephentoub I wonder if I should create a separate issue for this or should we just add the fix to this PR for the sake of simplicity?

@antonfirsov

antonfirsov commented Feb 27, 2020

Copy link
Copy Markdown
Contributor

A possible fix on my branch:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs#L3753-L3779

I had to change the expected exception for the test case to ConnectionRefused. The original code was returning InvalidArgument because of the bug:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs#L107-L130

My branch is also in sync with the current master, fixed two minor conflicts from #32675. @tmds can I update this PR with all these changes?

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

@stephentoub

stephentoub commented Feb 27, 2020

Copy link
Copy Markdown
Member

I wonder if I should create a separate issue for this

My preference would be to keep the bug fix and refactoring separate, ideally two PRs, but it could be two commits we don't squash if necessary.

@tmds

tmds commented Mar 2, 2020

Copy link
Copy Markdown
MemberAuthor

Thanks for having a look @antonfirsov! I hope Windows CI will now pass.

ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds a few points:

The Windows build is still failing in SocketAddress.Windows, you need _socketAddress!.Bufferhere.


Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

Have you also tried to address this?


ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

This means that we should enable this test now on Windows.

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

@tmds

tmds commented Mar 3, 2020

Copy link
Copy Markdown
MemberAuthor

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

I'll rewrite the PR in 2 commits when it compiles and tests pass.

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:

This is another Windows-specific problem? Can you take a look?

I wonder what the SocketError is in DoOperationConnect? Is it NotConnected?

internalunsafeSocketErrorDoOperationConnect(Socketsocket,SafeSocketHandlehandle)
{
// Called for connectionless protocols.
SocketErrorsocketError=SocketPal.Connect(handle,_socketAddress.Buffer,_socketAddress.Size);
FinishOperationSync(socketError,0,SocketFlags.None);
returnsocketError;
}

@tmds

tmds commented Mar 10, 2020

Copy link
Copy Markdown
MemberAuthor

@antonfirsov can you take a look at the remaining Windows issue?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds sure, was planning to do so today.

@antonfirsov

antonfirsov commented Mar 11, 2020

Copy link
Copy Markdown
Contributor

@tmds congratulations, you found another Windows-specific bug without using Windows!

Explanation + possible fix + relevant test case here.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

Explanation + possible fix + relevant test case here.

Thank you @antonfirsov ! I have included these changes. When CI passes, I will put UDP Connect(saea) into a separate PR.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

CI shows unrelated test failures in System.Reflection.Tests.TypeTests on mono.

And System.Net.Mail.Functional.Tests has an issue on netcoreapp5.0-Windows_NT-Release-x86-CoreCLR_release-Windows.10.Amd64.Server19H1.ES.Open:

Executed on a000HEL
C:\h\w\AEAD0979\w\AC6B091D\e>call RunTests.cmd --runtime-path C:\h\w\AEAD0979\p ----- start 17/03/2020 9:20:22,26 =============== To repro directly: ===================================================== pushd C:\h\w\AEAD0979\w\AC6B091D\e\
"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests popd
===========================================================================================================
C:\h\w\AEAD0979\w\AC6B091D\e>"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests Discovering: System.Net.Mail.Functional.Tests (method display = ClassAndMethod, method display options = None)
Discovered: System.Net.Mail.Functional.Tests (found 150 of 151 test cases)
Starting: System.Net.Mail.Functional.Tests (parallel test collections = on, max threads = 2)
----- end 17/03/2020 9:20:45,71 ----- exit code -1073740791 ----------------------------------------------------------
17/03/2020- 9:20:45,71
17/03/2020- 9:20:46,02
2020-03-17 09:20:46,477: INFO: 7880: run(82): main: Main thread starting 10 workers
Worker 0: starting...
Worker 1: starting...
Worker 2: starting...
Worker 3: starting...
Worker 4: starting...
Worker 5: starting...
Worker 6: starting...
Worker 7: starting...
Worker 8: starting...
Worker 9: starting...
2020-03-17 09:20:46,493: INFO: 7880: run(89): main: Beginning reading of test results.
2020-03-17 09:20:46,493: INFO: 7880: run(95): main: Uploading results in batches of size 1000
2020-03-17 09:20:46,493: INFO: 7880: run(100): main: Main thread finished queueing batches
2020-03-17 09:20:46,493: INFO: 7880: run(104): main: Main thread exiting
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e\..' for log files
Found log 'C:\h\w\AEAD0979\w\AC6B091D\e\..\console.f0a3d26b.log'
Uri 'https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D'
Generated log list: console.f0a3d26b.log:
https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e' for test results files
No results file found in any of the following formats: xunit, junit, trx
17/03/2020- 9:20:46,52
2020-03-17T09:20:47.212Z	ERROR xunit-reporter.py	xunit-reporter(80)	main	Unable to report xunit results: no test results xml file found.

with dump file: https://helix.dot.net/api/2019-06-17/jobs/b2b1e078-c6e7-4162-8f3f-c9c1d8e8300d/workitems/System.Net.Mail.Functional.Tests/files/dotnet.exe.8892.dmp

@tmds
tmdsforce-pushed the socket_connectasync branch from c0f2b7a to e5d3ed1CompareApril 6, 2020 15:57
[InlineData(65536)]
public async Task ConnectAsync_IPAddresses_InvalidPort_Throws_ArgumentOutOfRange(int port)
{
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => GetSocket().ConnectAsync(new[] { IPAddress.Loopback }, port));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
socket.Listen(1);
Assert.Throws<InvalidOperationException>(() => { socket.ConnectAsync(new[] { IPAddress.Loopback }, 1); });
await Assert.ThrowsAsync<InvalidOperationException>(() => socket.ConnectAsync(new[] { IPAddress.Loopback }, 1));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

}

if (usesApm)
if (UsesApm)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception thrown by the Task ConnectAsync methods has changed. The exceptions are now consistent with other Task-returning Socket methods.

@tmds

tmds commented Apr 6, 2020

Copy link
Copy Markdown
MemberAuthor

With #33674 merged, I've rebased this PR.

I've added some comments with the test changes that indicate changed behavior.

@stephentoubstephentoub left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Tom.

@stephentoub
stephentoub merged commit eab1d28 into dotnet:masterApr 27, 2020
@karelzkarelz added this to the 5.0.0 milestone Aug 18, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@tmds@stephentoub@antonfirsov@karelz@MihaZupan@Dotnet-GitSync-Bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs - #787

Merged
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync
Apr 27, 2020
Merged

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs#787
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync

Conversation

@tmds

@tmdstmds commented Dec 12, 2019

Copy link
Copy Markdown
Member

No description provided.

@tmds
tmds marked this pull request as ready for review December 12, 2019 09:03
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl @stephentoub this PR is not finished but I'd like some early feedback.
And, some of the test failures I get don't make sense to me (yet).

It seems github doesn't allow me to mark this as Draft and still do a CI run. Can you please mark this as no-merge?

@tmdstmds changed the title Refactor Task SocketAsync.ConnectAsync methods to use AwaitableSocketAsyncEventArgsRefactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgsDec 12, 2019
@tmds
tmdsforce-pushed the socket_connectasync branch from 749388f to ffcc63aCompareDecember 12, 2019 09:07
@MihaZupanMihaZupan added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Dec 12, 2019
@stephentoub

Copy link
Copy Markdown
Member

Thanks, @tmds. I'm concerned about doing something like this until https://github.com/dotnet/corefx/issues/39466 is addressed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@stephentoub

Copy link
Copy Markdown
Member

I'm concerned about doing something like this until dotnet/corefx#39466 is addressed.

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Comment threadsrc/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs Outdated
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Yes, it's on the Socket where it was used to Connect, so not keeping another Socket alive.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@scalablecory
scalablecory requested a review from a teamDecember 15, 2019 01:05
@stephentoubstephentoub removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jan 6, 2020
@stephentoub

Copy link
Copy Markdown
Member

@tmds, some of these test failures look relevant.

@tmds

tmds commented Jan 15, 2020

Copy link
Copy Markdown
MemberAuthor

This test is now failing on Windows:

[Fact]publicasyncTaskCtor_NotStream_ThrowsIOException(){using(Socketlistener=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp))using(Socketclient=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp)){listener.Bind(newIPEndPoint(IPAddress.Loopback,0));awaitclient.ConnectAsync(newIPEndPoint(IPAddress.Loopback,((IPEndPoint)listener.LocalEndPoint).Port));Assert.Throws<IOException>(()=>newNetworkStream(client));}}

Instead of throwing at the expected location, it's throwing on the ConnectAsync call above:

System.Net.Sockets.SocketException : An invalid argument was supplied.
 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/

I'm missing the fallback for connectionless protocols that is part of BeginConnect:

internalIAsyncResultUnsafeBeginConnect(EndPointremoteEP,AsyncCallbackcallback,objectstate,boolflowContext=false)
{
if(CanUseConnectEx(remoteEP))
{
returnBeginConnectEx(remoteEP,flowContext,callback,state);
}
EndPointendPointSnapshot=remoteEP;
varasyncResult=newConnectAsyncResult(this,endPointSnapshot,state,callback);
// For connectionless protocols, Connect is not an I/O call.
Connect(remoteEP);
asyncResult.FinishPostingAsyncOp();
// Synchronously complete the I/O and call the user's callback.
asyncResult.InvokeCallback();
returnasyncResult;
}

I'll add this and check if there are other things which may be missing.

@stephentoub

Copy link
Copy Markdown
Member

Thanks.

@tmds
tmdsforce-pushed the socket_connectasync branch from 4745f62 to 6404854CompareJanuary 30, 2020 13:57
@tmds

tmds commented Feb 10, 2020

Copy link
Copy Markdown
MemberAuthor

The latest change was to change ConnectAsync(SocketAsyncEventArgs) to make it work for UDP sockets. On Windows, the implementation was calling ConnectEx, but that isn't UDP compatible, so WSAConnect is now called instead:

if(CanUseConnectEx(endPointSnapshot)){socketError=e.DoOperationConnectEx(this,_handle);}else{// For connectionless protocols, Connect is not an I/O call.socketError=e.DoOperationConnect(this,_handle);}

I'm not sure if all parts of the CanUseConnectEx check apply here,. It does put us on the WSAConnect way, since the error message has changed:

System.Net.Sockets.SocketException : A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

with stacktrace

 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs:line 400
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/C

From the error message I'd guess WSAENOTCONN is returned by WSAConnect, but that doesn't show up on the WSAConnect doc page. I'm lost.

I don't have a Windows machine to debug.
@dotnet/ncl can someone help me make this work on Windows?

@tmds

tmds commented Feb 11, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@karelz can someone help me with this?

@tmds

tmds commented Feb 27, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@antonfirsov maybe you can have a look?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds your assumption was correct, CanUseConnectEx(...) does not return the right result on SocketAsyncEventArgs path, therefore ConnectEx is being called instead of WSAConnect.

This is even worse on master, since the original SocketAsyncEventArgs code path doesn't even try to check if it can use ConnectEx. The following code fails, which is a bug:

stringpath=Path.Combine(Path.GetTempPath(),Path.GetRandomFileName());varendPoint=newUnixDomainSocketEndPoint(path);usingvarserver=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);usingvarclient=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);server.Bind(endPoint);server.Listen(1);usingvarmre=newManualResetEventSlim(false);usingvarsea=newSocketAsyncEventArgs(){RemoteEndPoint=endPoint};sea.Completed+=(_,__)=>mre.Set();if(client.ConnectAsync(sea))mre.Wait();Assert.Equal(SocketError.Success,sea.SocketError);

@stephentoub I wonder if I should create a separate issue for this or should we just add the fix to this PR for the sake of simplicity?

@antonfirsov

antonfirsov commented Feb 27, 2020

Copy link
Copy Markdown
Contributor

A possible fix on my branch:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs#L3753-L3779

I had to change the expected exception for the test case to ConnectionRefused. The original code was returning InvalidArgument because of the bug:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs#L107-L130

My branch is also in sync with the current master, fixed two minor conflicts from #32675. @tmds can I update this PR with all these changes?

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

@stephentoub

stephentoub commented Feb 27, 2020

Copy link
Copy Markdown
Member

I wonder if I should create a separate issue for this

My preference would be to keep the bug fix and refactoring separate, ideally two PRs, but it could be two commits we don't squash if necessary.

@tmds

tmds commented Mar 2, 2020

Copy link
Copy Markdown
MemberAuthor

Thanks for having a look @antonfirsov! I hope Windows CI will now pass.

ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds a few points:

The Windows build is still failing in SocketAddress.Windows, you need _socketAddress!.Bufferhere.


Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

Have you also tried to address this?


ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

This means that we should enable this test now on Windows.

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

@tmds

tmds commented Mar 3, 2020

Copy link
Copy Markdown
MemberAuthor

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

I'll rewrite the PR in 2 commits when it compiles and tests pass.

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:

This is another Windows-specific problem? Can you take a look?

I wonder what the SocketError is in DoOperationConnect? Is it NotConnected?

internalunsafeSocketErrorDoOperationConnect(Socketsocket,SafeSocketHandlehandle)
{
// Called for connectionless protocols.
SocketErrorsocketError=SocketPal.Connect(handle,_socketAddress.Buffer,_socketAddress.Size);
FinishOperationSync(socketError,0,SocketFlags.None);
returnsocketError;
}

@tmds

tmds commented Mar 10, 2020

Copy link
Copy Markdown
MemberAuthor

@antonfirsov can you take a look at the remaining Windows issue?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds sure, was planning to do so today.

@antonfirsov

antonfirsov commented Mar 11, 2020

Copy link
Copy Markdown
Contributor

@tmds congratulations, you found another Windows-specific bug without using Windows!

Explanation + possible fix + relevant test case here.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

Explanation + possible fix + relevant test case here.

Thank you @antonfirsov ! I have included these changes. When CI passes, I will put UDP Connect(saea) into a separate PR.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

CI shows unrelated test failures in System.Reflection.Tests.TypeTests on mono.

And System.Net.Mail.Functional.Tests has an issue on netcoreapp5.0-Windows_NT-Release-x86-CoreCLR_release-Windows.10.Amd64.Server19H1.ES.Open:

Executed on a000HEL
C:\h\w\AEAD0979\w\AC6B091D\e>call RunTests.cmd --runtime-path C:\h\w\AEAD0979\p ----- start 17/03/2020 9:20:22,26 =============== To repro directly: ===================================================== pushd C:\h\w\AEAD0979\w\AC6B091D\e\
"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests popd
===========================================================================================================
C:\h\w\AEAD0979\w\AC6B091D\e>"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests Discovering: System.Net.Mail.Functional.Tests (method display = ClassAndMethod, method display options = None)
Discovered: System.Net.Mail.Functional.Tests (found 150 of 151 test cases)
Starting: System.Net.Mail.Functional.Tests (parallel test collections = on, max threads = 2)
----- end 17/03/2020 9:20:45,71 ----- exit code -1073740791 ----------------------------------------------------------
17/03/2020- 9:20:45,71
17/03/2020- 9:20:46,02
2020-03-17 09:20:46,477: INFO: 7880: run(82): main: Main thread starting 10 workers
Worker 0: starting...
Worker 1: starting...
Worker 2: starting...
Worker 3: starting...
Worker 4: starting...
Worker 5: starting...
Worker 6: starting...
Worker 7: starting...
Worker 8: starting...
Worker 9: starting...
2020-03-17 09:20:46,493: INFO: 7880: run(89): main: Beginning reading of test results.
2020-03-17 09:20:46,493: INFO: 7880: run(95): main: Uploading results in batches of size 1000
2020-03-17 09:20:46,493: INFO: 7880: run(100): main: Main thread finished queueing batches
2020-03-17 09:20:46,493: INFO: 7880: run(104): main: Main thread exiting
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e\..' for log files
Found log 'C:\h\w\AEAD0979\w\AC6B091D\e\..\console.f0a3d26b.log'
Uri 'https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D'
Generated log list: console.f0a3d26b.log:
https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e' for test results files
No results file found in any of the following formats: xunit, junit, trx
17/03/2020- 9:20:46,52
2020-03-17T09:20:47.212Z	ERROR xunit-reporter.py	xunit-reporter(80)	main	Unable to report xunit results: no test results xml file found.

with dump file: https://helix.dot.net/api/2019-06-17/jobs/b2b1e078-c6e7-4162-8f3f-c9c1d8e8300d/workitems/System.Net.Mail.Functional.Tests/files/dotnet.exe.8892.dmp

@tmds
tmdsforce-pushed the socket_connectasync branch from c0f2b7a to e5d3ed1CompareApril 6, 2020 15:57
[InlineData(65536)]
public async Task ConnectAsync_IPAddresses_InvalidPort_Throws_ArgumentOutOfRange(int port)
{
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => GetSocket().ConnectAsync(new[] { IPAddress.Loopback }, port));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
socket.Listen(1);
Assert.Throws<InvalidOperationException>(() => { socket.ConnectAsync(new[] { IPAddress.Loopback }, 1); });
await Assert.ThrowsAsync<InvalidOperationException>(() => socket.ConnectAsync(new[] { IPAddress.Loopback }, 1));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

}

if (usesApm)
if (UsesApm)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception thrown by the Task ConnectAsync methods has changed. The exceptions are now consistent with other Task-returning Socket methods.

@tmds

tmds commented Apr 6, 2020

Copy link
Copy Markdown
MemberAuthor

With #33674 merged, I've rebased this PR.

I've added some comments with the test changes that indicate changed behavior.

@stephentoubstephentoub left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Tom.

@stephentoub
stephentoub merged commit eab1d28 into dotnet:masterApr 27, 2020
@karelzkarelz added this to the 5.0.0 milestone Aug 18, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@tmds@stephentoub@antonfirsov@karelz@MihaZupan@Dotnet-GitSync-Bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs - #787

Merged
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync
Apr 27, 2020
Merged

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs#787
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync

Conversation

@tmds

@tmdstmds commented Dec 12, 2019

Copy link
Copy Markdown
Member

No description provided.

@tmds
tmds marked this pull request as ready for review December 12, 2019 09:03
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl @stephentoub this PR is not finished but I'd like some early feedback.
And, some of the test failures I get don't make sense to me (yet).

It seems github doesn't allow me to mark this as Draft and still do a CI run. Can you please mark this as no-merge?

@tmdstmds changed the title Refactor Task SocketAsync.ConnectAsync methods to use AwaitableSocketAsyncEventArgsRefactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgsDec 12, 2019
@tmds
tmdsforce-pushed the socket_connectasync branch from 749388f to ffcc63aCompareDecember 12, 2019 09:07
@MihaZupanMihaZupan added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Dec 12, 2019
@stephentoub

Copy link
Copy Markdown
Member

Thanks, @tmds. I'm concerned about doing something like this until https://github.com/dotnet/corefx/issues/39466 is addressed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@stephentoub

Copy link
Copy Markdown
Member

I'm concerned about doing something like this until dotnet/corefx#39466 is addressed.

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Comment threadsrc/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs Outdated
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Yes, it's on the Socket where it was used to Connect, so not keeping another Socket alive.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@scalablecory
scalablecory requested a review from a teamDecember 15, 2019 01:05
@stephentoubstephentoub removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jan 6, 2020
@stephentoub

Copy link
Copy Markdown
Member

@tmds, some of these test failures look relevant.

@tmds

tmds commented Jan 15, 2020

Copy link
Copy Markdown
MemberAuthor

This test is now failing on Windows:

[Fact]publicasyncTaskCtor_NotStream_ThrowsIOException(){using(Socketlistener=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp))using(Socketclient=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp)){listener.Bind(newIPEndPoint(IPAddress.Loopback,0));awaitclient.ConnectAsync(newIPEndPoint(IPAddress.Loopback,((IPEndPoint)listener.LocalEndPoint).Port));Assert.Throws<IOException>(()=>newNetworkStream(client));}}

Instead of throwing at the expected location, it's throwing on the ConnectAsync call above:

System.Net.Sockets.SocketException : An invalid argument was supplied.
 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/

I'm missing the fallback for connectionless protocols that is part of BeginConnect:

internalIAsyncResultUnsafeBeginConnect(EndPointremoteEP,AsyncCallbackcallback,objectstate,boolflowContext=false)
{
if(CanUseConnectEx(remoteEP))
{
returnBeginConnectEx(remoteEP,flowContext,callback,state);
}
EndPointendPointSnapshot=remoteEP;
varasyncResult=newConnectAsyncResult(this,endPointSnapshot,state,callback);
// For connectionless protocols, Connect is not an I/O call.
Connect(remoteEP);
asyncResult.FinishPostingAsyncOp();
// Synchronously complete the I/O and call the user's callback.
asyncResult.InvokeCallback();
returnasyncResult;
}

I'll add this and check if there are other things which may be missing.

@stephentoub

Copy link
Copy Markdown
Member

Thanks.

@tmds
tmdsforce-pushed the socket_connectasync branch from 4745f62 to 6404854CompareJanuary 30, 2020 13:57
@tmds

tmds commented Feb 10, 2020

Copy link
Copy Markdown
MemberAuthor

The latest change was to change ConnectAsync(SocketAsyncEventArgs) to make it work for UDP sockets. On Windows, the implementation was calling ConnectEx, but that isn't UDP compatible, so WSAConnect is now called instead:

if(CanUseConnectEx(endPointSnapshot)){socketError=e.DoOperationConnectEx(this,_handle);}else{// For connectionless protocols, Connect is not an I/O call.socketError=e.DoOperationConnect(this,_handle);}

I'm not sure if all parts of the CanUseConnectEx check apply here,. It does put us on the WSAConnect way, since the error message has changed:

System.Net.Sockets.SocketException : A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

with stacktrace

 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs:line 400
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/C

From the error message I'd guess WSAENOTCONN is returned by WSAConnect, but that doesn't show up on the WSAConnect doc page. I'm lost.

I don't have a Windows machine to debug.
@dotnet/ncl can someone help me make this work on Windows?

@tmds

tmds commented Feb 11, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@karelz can someone help me with this?

@tmds

tmds commented Feb 27, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@antonfirsov maybe you can have a look?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds your assumption was correct, CanUseConnectEx(...) does not return the right result on SocketAsyncEventArgs path, therefore ConnectEx is being called instead of WSAConnect.

This is even worse on master, since the original SocketAsyncEventArgs code path doesn't even try to check if it can use ConnectEx. The following code fails, which is a bug:

stringpath=Path.Combine(Path.GetTempPath(),Path.GetRandomFileName());varendPoint=newUnixDomainSocketEndPoint(path);usingvarserver=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);usingvarclient=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);server.Bind(endPoint);server.Listen(1);usingvarmre=newManualResetEventSlim(false);usingvarsea=newSocketAsyncEventArgs(){RemoteEndPoint=endPoint};sea.Completed+=(_,__)=>mre.Set();if(client.ConnectAsync(sea))mre.Wait();Assert.Equal(SocketError.Success,sea.SocketError);

@stephentoub I wonder if I should create a separate issue for this or should we just add the fix to this PR for the sake of simplicity?

@antonfirsov

antonfirsov commented Feb 27, 2020

Copy link
Copy Markdown
Contributor

A possible fix on my branch:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs#L3753-L3779

I had to change the expected exception for the test case to ConnectionRefused. The original code was returning InvalidArgument because of the bug:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs#L107-L130

My branch is also in sync with the current master, fixed two minor conflicts from #32675. @tmds can I update this PR with all these changes?

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

@stephentoub

stephentoub commented Feb 27, 2020

Copy link
Copy Markdown
Member

I wonder if I should create a separate issue for this

My preference would be to keep the bug fix and refactoring separate, ideally two PRs, but it could be two commits we don't squash if necessary.

@tmds

tmds commented Mar 2, 2020

Copy link
Copy Markdown
MemberAuthor

Thanks for having a look @antonfirsov! I hope Windows CI will now pass.

ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds a few points:

The Windows build is still failing in SocketAddress.Windows, you need _socketAddress!.Bufferhere.


Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

Have you also tried to address this?


ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

This means that we should enable this test now on Windows.

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

@tmds

tmds commented Mar 3, 2020

Copy link
Copy Markdown
MemberAuthor

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

I'll rewrite the PR in 2 commits when it compiles and tests pass.

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:

This is another Windows-specific problem? Can you take a look?

I wonder what the SocketError is in DoOperationConnect? Is it NotConnected?

internalunsafeSocketErrorDoOperationConnect(Socketsocket,SafeSocketHandlehandle)
{
// Called for connectionless protocols.
SocketErrorsocketError=SocketPal.Connect(handle,_socketAddress.Buffer,_socketAddress.Size);
FinishOperationSync(socketError,0,SocketFlags.None);
returnsocketError;
}

@tmds

tmds commented Mar 10, 2020

Copy link
Copy Markdown
MemberAuthor

@antonfirsov can you take a look at the remaining Windows issue?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds sure, was planning to do so today.

@antonfirsov

antonfirsov commented Mar 11, 2020

Copy link
Copy Markdown
Contributor

@tmds congratulations, you found another Windows-specific bug without using Windows!

Explanation + possible fix + relevant test case here.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

Explanation + possible fix + relevant test case here.

Thank you @antonfirsov ! I have included these changes. When CI passes, I will put UDP Connect(saea) into a separate PR.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

CI shows unrelated test failures in System.Reflection.Tests.TypeTests on mono.

And System.Net.Mail.Functional.Tests has an issue on netcoreapp5.0-Windows_NT-Release-x86-CoreCLR_release-Windows.10.Amd64.Server19H1.ES.Open:

Executed on a000HEL
C:\h\w\AEAD0979\w\AC6B091D\e>call RunTests.cmd --runtime-path C:\h\w\AEAD0979\p ----- start 17/03/2020 9:20:22,26 =============== To repro directly: ===================================================== pushd C:\h\w\AEAD0979\w\AC6B091D\e\
"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests popd
===========================================================================================================
C:\h\w\AEAD0979\w\AC6B091D\e>"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests Discovering: System.Net.Mail.Functional.Tests (method display = ClassAndMethod, method display options = None)
Discovered: System.Net.Mail.Functional.Tests (found 150 of 151 test cases)
Starting: System.Net.Mail.Functional.Tests (parallel test collections = on, max threads = 2)
----- end 17/03/2020 9:20:45,71 ----- exit code -1073740791 ----------------------------------------------------------
17/03/2020- 9:20:45,71
17/03/2020- 9:20:46,02
2020-03-17 09:20:46,477: INFO: 7880: run(82): main: Main thread starting 10 workers
Worker 0: starting...
Worker 1: starting...
Worker 2: starting...
Worker 3: starting...
Worker 4: starting...
Worker 5: starting...
Worker 6: starting...
Worker 7: starting...
Worker 8: starting...
Worker 9: starting...
2020-03-17 09:20:46,493: INFO: 7880: run(89): main: Beginning reading of test results.
2020-03-17 09:20:46,493: INFO: 7880: run(95): main: Uploading results in batches of size 1000
2020-03-17 09:20:46,493: INFO: 7880: run(100): main: Main thread finished queueing batches
2020-03-17 09:20:46,493: INFO: 7880: run(104): main: Main thread exiting
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e\..' for log files
Found log 'C:\h\w\AEAD0979\w\AC6B091D\e\..\console.f0a3d26b.log'
Uri 'https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D'
Generated log list: console.f0a3d26b.log:
https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e' for test results files
No results file found in any of the following formats: xunit, junit, trx
17/03/2020- 9:20:46,52
2020-03-17T09:20:47.212Z	ERROR xunit-reporter.py	xunit-reporter(80)	main	Unable to report xunit results: no test results xml file found.

with dump file: https://helix.dot.net/api/2019-06-17/jobs/b2b1e078-c6e7-4162-8f3f-c9c1d8e8300d/workitems/System.Net.Mail.Functional.Tests/files/dotnet.exe.8892.dmp

@tmds
tmdsforce-pushed the socket_connectasync branch from c0f2b7a to e5d3ed1CompareApril 6, 2020 15:57
[InlineData(65536)]
public async Task ConnectAsync_IPAddresses_InvalidPort_Throws_ArgumentOutOfRange(int port)
{
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => GetSocket().ConnectAsync(new[] { IPAddress.Loopback }, port));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
socket.Listen(1);
Assert.Throws<InvalidOperationException>(() => { socket.ConnectAsync(new[] { IPAddress.Loopback }, 1); });
await Assert.ThrowsAsync<InvalidOperationException>(() => socket.ConnectAsync(new[] { IPAddress.Loopback }, 1));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

}

if (usesApm)
if (UsesApm)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception thrown by the Task ConnectAsync methods has changed. The exceptions are now consistent with other Task-returning Socket methods.

@tmds

tmds commented Apr 6, 2020

Copy link
Copy Markdown
MemberAuthor

With #33674 merged, I've rebased this PR.

I've added some comments with the test changes that indicate changed behavior.

@stephentoubstephentoub left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Tom.

@stephentoub
stephentoub merged commit eab1d28 into dotnet:masterApr 27, 2020
@karelzkarelz added this to the 5.0.0 milestone Aug 18, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@tmds@stephentoub@antonfirsov@karelz@MihaZupan@Dotnet-GitSync-Bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs - #787

Merged
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync
Apr 27, 2020
Merged

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs#787
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync

Conversation

@tmds

@tmdstmds commented Dec 12, 2019

Copy link
Copy Markdown
Member

No description provided.

@tmds
tmds marked this pull request as ready for review December 12, 2019 09:03
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl @stephentoub this PR is not finished but I'd like some early feedback.
And, some of the test failures I get don't make sense to me (yet).

It seems github doesn't allow me to mark this as Draft and still do a CI run. Can you please mark this as no-merge?

@tmdstmds changed the title Refactor Task SocketAsync.ConnectAsync methods to use AwaitableSocketAsyncEventArgsRefactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgsDec 12, 2019
@tmds
tmdsforce-pushed the socket_connectasync branch from 749388f to ffcc63aCompareDecember 12, 2019 09:07
@MihaZupanMihaZupan added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Dec 12, 2019
@stephentoub

Copy link
Copy Markdown
Member

Thanks, @tmds. I'm concerned about doing something like this until https://github.com/dotnet/corefx/issues/39466 is addressed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@stephentoub

Copy link
Copy Markdown
Member

I'm concerned about doing something like this until dotnet/corefx#39466 is addressed.

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Comment threadsrc/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs Outdated
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Yes, it's on the Socket where it was used to Connect, so not keeping another Socket alive.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@scalablecory
scalablecory requested a review from a teamDecember 15, 2019 01:05
@stephentoubstephentoub removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jan 6, 2020
@stephentoub

Copy link
Copy Markdown
Member

@tmds, some of these test failures look relevant.

@tmds

tmds commented Jan 15, 2020

Copy link
Copy Markdown
MemberAuthor

This test is now failing on Windows:

[Fact]publicasyncTaskCtor_NotStream_ThrowsIOException(){using(Socketlistener=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp))using(Socketclient=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp)){listener.Bind(newIPEndPoint(IPAddress.Loopback,0));awaitclient.ConnectAsync(newIPEndPoint(IPAddress.Loopback,((IPEndPoint)listener.LocalEndPoint).Port));Assert.Throws<IOException>(()=>newNetworkStream(client));}}

Instead of throwing at the expected location, it's throwing on the ConnectAsync call above:

System.Net.Sockets.SocketException : An invalid argument was supplied.
 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/

I'm missing the fallback for connectionless protocols that is part of BeginConnect:

internalIAsyncResultUnsafeBeginConnect(EndPointremoteEP,AsyncCallbackcallback,objectstate,boolflowContext=false)
{
if(CanUseConnectEx(remoteEP))
{
returnBeginConnectEx(remoteEP,flowContext,callback,state);
}
EndPointendPointSnapshot=remoteEP;
varasyncResult=newConnectAsyncResult(this,endPointSnapshot,state,callback);
// For connectionless protocols, Connect is not an I/O call.
Connect(remoteEP);
asyncResult.FinishPostingAsyncOp();
// Synchronously complete the I/O and call the user's callback.
asyncResult.InvokeCallback();
returnasyncResult;
}

I'll add this and check if there are other things which may be missing.

@stephentoub

Copy link
Copy Markdown
Member

Thanks.

@tmds
tmdsforce-pushed the socket_connectasync branch from 4745f62 to 6404854CompareJanuary 30, 2020 13:57
@tmds

tmds commented Feb 10, 2020

Copy link
Copy Markdown
MemberAuthor

The latest change was to change ConnectAsync(SocketAsyncEventArgs) to make it work for UDP sockets. On Windows, the implementation was calling ConnectEx, but that isn't UDP compatible, so WSAConnect is now called instead:

if(CanUseConnectEx(endPointSnapshot)){socketError=e.DoOperationConnectEx(this,_handle);}else{// For connectionless protocols, Connect is not an I/O call.socketError=e.DoOperationConnect(this,_handle);}

I'm not sure if all parts of the CanUseConnectEx check apply here,. It does put us on the WSAConnect way, since the error message has changed:

System.Net.Sockets.SocketException : A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

with stacktrace

 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs:line 400
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/C

From the error message I'd guess WSAENOTCONN is returned by WSAConnect, but that doesn't show up on the WSAConnect doc page. I'm lost.

I don't have a Windows machine to debug.
@dotnet/ncl can someone help me make this work on Windows?

@tmds

tmds commented Feb 11, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@karelz can someone help me with this?

@tmds

tmds commented Feb 27, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@antonfirsov maybe you can have a look?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds your assumption was correct, CanUseConnectEx(...) does not return the right result on SocketAsyncEventArgs path, therefore ConnectEx is being called instead of WSAConnect.

This is even worse on master, since the original SocketAsyncEventArgs code path doesn't even try to check if it can use ConnectEx. The following code fails, which is a bug:

stringpath=Path.Combine(Path.GetTempPath(),Path.GetRandomFileName());varendPoint=newUnixDomainSocketEndPoint(path);usingvarserver=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);usingvarclient=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);server.Bind(endPoint);server.Listen(1);usingvarmre=newManualResetEventSlim(false);usingvarsea=newSocketAsyncEventArgs(){RemoteEndPoint=endPoint};sea.Completed+=(_,__)=>mre.Set();if(client.ConnectAsync(sea))mre.Wait();Assert.Equal(SocketError.Success,sea.SocketError);

@stephentoub I wonder if I should create a separate issue for this or should we just add the fix to this PR for the sake of simplicity?

@antonfirsov

antonfirsov commented Feb 27, 2020

Copy link
Copy Markdown
Contributor

A possible fix on my branch:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs#L3753-L3779

I had to change the expected exception for the test case to ConnectionRefused. The original code was returning InvalidArgument because of the bug:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs#L107-L130

My branch is also in sync with the current master, fixed two minor conflicts from #32675. @tmds can I update this PR with all these changes?

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

@stephentoub

stephentoub commented Feb 27, 2020

Copy link
Copy Markdown
Member

I wonder if I should create a separate issue for this

My preference would be to keep the bug fix and refactoring separate, ideally two PRs, but it could be two commits we don't squash if necessary.

@tmds

tmds commented Mar 2, 2020

Copy link
Copy Markdown
MemberAuthor

Thanks for having a look @antonfirsov! I hope Windows CI will now pass.

ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds a few points:

The Windows build is still failing in SocketAddress.Windows, you need _socketAddress!.Bufferhere.


Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

Have you also tried to address this?


ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

This means that we should enable this test now on Windows.

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

@tmds

tmds commented Mar 3, 2020

Copy link
Copy Markdown
MemberAuthor

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

I'll rewrite the PR in 2 commits when it compiles and tests pass.

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:

This is another Windows-specific problem? Can you take a look?

I wonder what the SocketError is in DoOperationConnect? Is it NotConnected?

internalunsafeSocketErrorDoOperationConnect(Socketsocket,SafeSocketHandlehandle)
{
// Called for connectionless protocols.
SocketErrorsocketError=SocketPal.Connect(handle,_socketAddress.Buffer,_socketAddress.Size);
FinishOperationSync(socketError,0,SocketFlags.None);
returnsocketError;
}

@tmds

tmds commented Mar 10, 2020

Copy link
Copy Markdown
MemberAuthor

@antonfirsov can you take a look at the remaining Windows issue?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds sure, was planning to do so today.

@antonfirsov

antonfirsov commented Mar 11, 2020

Copy link
Copy Markdown
Contributor

@tmds congratulations, you found another Windows-specific bug without using Windows!

Explanation + possible fix + relevant test case here.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

Explanation + possible fix + relevant test case here.

Thank you @antonfirsov ! I have included these changes. When CI passes, I will put UDP Connect(saea) into a separate PR.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

CI shows unrelated test failures in System.Reflection.Tests.TypeTests on mono.

And System.Net.Mail.Functional.Tests has an issue on netcoreapp5.0-Windows_NT-Release-x86-CoreCLR_release-Windows.10.Amd64.Server19H1.ES.Open:

Executed on a000HEL
C:\h\w\AEAD0979\w\AC6B091D\e>call RunTests.cmd --runtime-path C:\h\w\AEAD0979\p ----- start 17/03/2020 9:20:22,26 =============== To repro directly: ===================================================== pushd C:\h\w\AEAD0979\w\AC6B091D\e\
"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests popd
===========================================================================================================
C:\h\w\AEAD0979\w\AC6B091D\e>"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests Discovering: System.Net.Mail.Functional.Tests (method display = ClassAndMethod, method display options = None)
Discovered: System.Net.Mail.Functional.Tests (found 150 of 151 test cases)
Starting: System.Net.Mail.Functional.Tests (parallel test collections = on, max threads = 2)
----- end 17/03/2020 9:20:45,71 ----- exit code -1073740791 ----------------------------------------------------------
17/03/2020- 9:20:45,71
17/03/2020- 9:20:46,02
2020-03-17 09:20:46,477: INFO: 7880: run(82): main: Main thread starting 10 workers
Worker 0: starting...
Worker 1: starting...
Worker 2: starting...
Worker 3: starting...
Worker 4: starting...
Worker 5: starting...
Worker 6: starting...
Worker 7: starting...
Worker 8: starting...
Worker 9: starting...
2020-03-17 09:20:46,493: INFO: 7880: run(89): main: Beginning reading of test results.
2020-03-17 09:20:46,493: INFO: 7880: run(95): main: Uploading results in batches of size 1000
2020-03-17 09:20:46,493: INFO: 7880: run(100): main: Main thread finished queueing batches
2020-03-17 09:20:46,493: INFO: 7880: run(104): main: Main thread exiting
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e\..' for log files
Found log 'C:\h\w\AEAD0979\w\AC6B091D\e\..\console.f0a3d26b.log'
Uri 'https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D'
Generated log list: console.f0a3d26b.log:
https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e' for test results files
No results file found in any of the following formats: xunit, junit, trx
17/03/2020- 9:20:46,52
2020-03-17T09:20:47.212Z	ERROR xunit-reporter.py	xunit-reporter(80)	main	Unable to report xunit results: no test results xml file found.

with dump file: https://helix.dot.net/api/2019-06-17/jobs/b2b1e078-c6e7-4162-8f3f-c9c1d8e8300d/workitems/System.Net.Mail.Functional.Tests/files/dotnet.exe.8892.dmp

@tmds
tmdsforce-pushed the socket_connectasync branch from c0f2b7a to e5d3ed1CompareApril 6, 2020 15:57
[InlineData(65536)]
public async Task ConnectAsync_IPAddresses_InvalidPort_Throws_ArgumentOutOfRange(int port)
{
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => GetSocket().ConnectAsync(new[] { IPAddress.Loopback }, port));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
socket.Listen(1);
Assert.Throws<InvalidOperationException>(() => { socket.ConnectAsync(new[] { IPAddress.Loopback }, 1); });
await Assert.ThrowsAsync<InvalidOperationException>(() => socket.ConnectAsync(new[] { IPAddress.Loopback }, 1));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

}

if (usesApm)
if (UsesApm)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception thrown by the Task ConnectAsync methods has changed. The exceptions are now consistent with other Task-returning Socket methods.

@tmds

tmds commented Apr 6, 2020

Copy link
Copy Markdown
MemberAuthor

With #33674 merged, I've rebased this PR.

I've added some comments with the test changes that indicate changed behavior.

@stephentoubstephentoub left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Tom.

@stephentoub
stephentoub merged commit eab1d28 into dotnet:masterApr 27, 2020
@karelzkarelz added this to the 5.0.0 milestone Aug 18, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@tmds@stephentoub@antonfirsov@karelz@MihaZupan@Dotnet-GitSync-Bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs - #787

Merged
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync
Apr 27, 2020
Merged

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs#787
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync

Conversation

@tmds

@tmdstmds commented Dec 12, 2019

Copy link
Copy Markdown
Member

No description provided.

@tmds
tmds marked this pull request as ready for review December 12, 2019 09:03
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl @stephentoub this PR is not finished but I'd like some early feedback.
And, some of the test failures I get don't make sense to me (yet).

It seems github doesn't allow me to mark this as Draft and still do a CI run. Can you please mark this as no-merge?

@tmdstmds changed the title Refactor Task SocketAsync.ConnectAsync methods to use AwaitableSocketAsyncEventArgsRefactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgsDec 12, 2019
@tmds
tmdsforce-pushed the socket_connectasync branch from 749388f to ffcc63aCompareDecember 12, 2019 09:07
@MihaZupanMihaZupan added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Dec 12, 2019
@stephentoub

Copy link
Copy Markdown
Member

Thanks, @tmds. I'm concerned about doing something like this until https://github.com/dotnet/corefx/issues/39466 is addressed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@stephentoub

Copy link
Copy Markdown
Member

I'm concerned about doing something like this until dotnet/corefx#39466 is addressed.

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Comment threadsrc/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs Outdated
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Yes, it's on the Socket where it was used to Connect, so not keeping another Socket alive.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@scalablecory
scalablecory requested a review from a teamDecember 15, 2019 01:05
@stephentoubstephentoub removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jan 6, 2020
@stephentoub

Copy link
Copy Markdown
Member

@tmds, some of these test failures look relevant.

@tmds

tmds commented Jan 15, 2020

Copy link
Copy Markdown
MemberAuthor

This test is now failing on Windows:

[Fact]publicasyncTaskCtor_NotStream_ThrowsIOException(){using(Socketlistener=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp))using(Socketclient=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp)){listener.Bind(newIPEndPoint(IPAddress.Loopback,0));awaitclient.ConnectAsync(newIPEndPoint(IPAddress.Loopback,((IPEndPoint)listener.LocalEndPoint).Port));Assert.Throws<IOException>(()=>newNetworkStream(client));}}

Instead of throwing at the expected location, it's throwing on the ConnectAsync call above:

System.Net.Sockets.SocketException : An invalid argument was supplied.
 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/

I'm missing the fallback for connectionless protocols that is part of BeginConnect:

internalIAsyncResultUnsafeBeginConnect(EndPointremoteEP,AsyncCallbackcallback,objectstate,boolflowContext=false)
{
if(CanUseConnectEx(remoteEP))
{
returnBeginConnectEx(remoteEP,flowContext,callback,state);
}
EndPointendPointSnapshot=remoteEP;
varasyncResult=newConnectAsyncResult(this,endPointSnapshot,state,callback);
// For connectionless protocols, Connect is not an I/O call.
Connect(remoteEP);
asyncResult.FinishPostingAsyncOp();
// Synchronously complete the I/O and call the user's callback.
asyncResult.InvokeCallback();
returnasyncResult;
}

I'll add this and check if there are other things which may be missing.

@stephentoub

Copy link
Copy Markdown
Member

Thanks.

@tmds
tmdsforce-pushed the socket_connectasync branch from 4745f62 to 6404854CompareJanuary 30, 2020 13:57
@tmds

tmds commented Feb 10, 2020

Copy link
Copy Markdown
MemberAuthor

The latest change was to change ConnectAsync(SocketAsyncEventArgs) to make it work for UDP sockets. On Windows, the implementation was calling ConnectEx, but that isn't UDP compatible, so WSAConnect is now called instead:

if(CanUseConnectEx(endPointSnapshot)){socketError=e.DoOperationConnectEx(this,_handle);}else{// For connectionless protocols, Connect is not an I/O call.socketError=e.DoOperationConnect(this,_handle);}

I'm not sure if all parts of the CanUseConnectEx check apply here,. It does put us on the WSAConnect way, since the error message has changed:

System.Net.Sockets.SocketException : A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

with stacktrace

 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs:line 400
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/C

From the error message I'd guess WSAENOTCONN is returned by WSAConnect, but that doesn't show up on the WSAConnect doc page. I'm lost.

I don't have a Windows machine to debug.
@dotnet/ncl can someone help me make this work on Windows?

@tmds

tmds commented Feb 11, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@karelz can someone help me with this?

@tmds

tmds commented Feb 27, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@antonfirsov maybe you can have a look?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds your assumption was correct, CanUseConnectEx(...) does not return the right result on SocketAsyncEventArgs path, therefore ConnectEx is being called instead of WSAConnect.

This is even worse on master, since the original SocketAsyncEventArgs code path doesn't even try to check if it can use ConnectEx. The following code fails, which is a bug:

stringpath=Path.Combine(Path.GetTempPath(),Path.GetRandomFileName());varendPoint=newUnixDomainSocketEndPoint(path);usingvarserver=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);usingvarclient=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);server.Bind(endPoint);server.Listen(1);usingvarmre=newManualResetEventSlim(false);usingvarsea=newSocketAsyncEventArgs(){RemoteEndPoint=endPoint};sea.Completed+=(_,__)=>mre.Set();if(client.ConnectAsync(sea))mre.Wait();Assert.Equal(SocketError.Success,sea.SocketError);

@stephentoub I wonder if I should create a separate issue for this or should we just add the fix to this PR for the sake of simplicity?

@antonfirsov

antonfirsov commented Feb 27, 2020

Copy link
Copy Markdown
Contributor

A possible fix on my branch:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs#L3753-L3779

I had to change the expected exception for the test case to ConnectionRefused. The original code was returning InvalidArgument because of the bug:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs#L107-L130

My branch is also in sync with the current master, fixed two minor conflicts from #32675. @tmds can I update this PR with all these changes?

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

@stephentoub

stephentoub commented Feb 27, 2020

Copy link
Copy Markdown
Member

I wonder if I should create a separate issue for this

My preference would be to keep the bug fix and refactoring separate, ideally two PRs, but it could be two commits we don't squash if necessary.

@tmds

tmds commented Mar 2, 2020

Copy link
Copy Markdown
MemberAuthor

Thanks for having a look @antonfirsov! I hope Windows CI will now pass.

ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds a few points:

The Windows build is still failing in SocketAddress.Windows, you need _socketAddress!.Bufferhere.


Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

Have you also tried to address this?


ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

This means that we should enable this test now on Windows.

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

@tmds

tmds commented Mar 3, 2020

Copy link
Copy Markdown
MemberAuthor

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

I'll rewrite the PR in 2 commits when it compiles and tests pass.

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:

This is another Windows-specific problem? Can you take a look?

I wonder what the SocketError is in DoOperationConnect? Is it NotConnected?

internalunsafeSocketErrorDoOperationConnect(Socketsocket,SafeSocketHandlehandle)
{
// Called for connectionless protocols.
SocketErrorsocketError=SocketPal.Connect(handle,_socketAddress.Buffer,_socketAddress.Size);
FinishOperationSync(socketError,0,SocketFlags.None);
returnsocketError;
}

@tmds

tmds commented Mar 10, 2020

Copy link
Copy Markdown
MemberAuthor

@antonfirsov can you take a look at the remaining Windows issue?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds sure, was planning to do so today.

@antonfirsov

antonfirsov commented Mar 11, 2020

Copy link
Copy Markdown
Contributor

@tmds congratulations, you found another Windows-specific bug without using Windows!

Explanation + possible fix + relevant test case here.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

Explanation + possible fix + relevant test case here.

Thank you @antonfirsov ! I have included these changes. When CI passes, I will put UDP Connect(saea) into a separate PR.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

CI shows unrelated test failures in System.Reflection.Tests.TypeTests on mono.

And System.Net.Mail.Functional.Tests has an issue on netcoreapp5.0-Windows_NT-Release-x86-CoreCLR_release-Windows.10.Amd64.Server19H1.ES.Open:

Executed on a000HEL
C:\h\w\AEAD0979\w\AC6B091D\e>call RunTests.cmd --runtime-path C:\h\w\AEAD0979\p ----- start 17/03/2020 9:20:22,26 =============== To repro directly: ===================================================== pushd C:\h\w\AEAD0979\w\AC6B091D\e\
"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests popd
===========================================================================================================
C:\h\w\AEAD0979\w\AC6B091D\e>"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests Discovering: System.Net.Mail.Functional.Tests (method display = ClassAndMethod, method display options = None)
Discovered: System.Net.Mail.Functional.Tests (found 150 of 151 test cases)
Starting: System.Net.Mail.Functional.Tests (parallel test collections = on, max threads = 2)
----- end 17/03/2020 9:20:45,71 ----- exit code -1073740791 ----------------------------------------------------------
17/03/2020- 9:20:45,71
17/03/2020- 9:20:46,02
2020-03-17 09:20:46,477: INFO: 7880: run(82): main: Main thread starting 10 workers
Worker 0: starting...
Worker 1: starting...
Worker 2: starting...
Worker 3: starting...
Worker 4: starting...
Worker 5: starting...
Worker 6: starting...
Worker 7: starting...
Worker 8: starting...
Worker 9: starting...
2020-03-17 09:20:46,493: INFO: 7880: run(89): main: Beginning reading of test results.
2020-03-17 09:20:46,493: INFO: 7880: run(95): main: Uploading results in batches of size 1000
2020-03-17 09:20:46,493: INFO: 7880: run(100): main: Main thread finished queueing batches
2020-03-17 09:20:46,493: INFO: 7880: run(104): main: Main thread exiting
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e\..' for log files
Found log 'C:\h\w\AEAD0979\w\AC6B091D\e\..\console.f0a3d26b.log'
Uri 'https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D'
Generated log list: console.f0a3d26b.log:
https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e' for test results files
No results file found in any of the following formats: xunit, junit, trx
17/03/2020- 9:20:46,52
2020-03-17T09:20:47.212Z	ERROR xunit-reporter.py	xunit-reporter(80)	main	Unable to report xunit results: no test results xml file found.

with dump file: https://helix.dot.net/api/2019-06-17/jobs/b2b1e078-c6e7-4162-8f3f-c9c1d8e8300d/workitems/System.Net.Mail.Functional.Tests/files/dotnet.exe.8892.dmp

@tmds
tmdsforce-pushed the socket_connectasync branch from c0f2b7a to e5d3ed1CompareApril 6, 2020 15:57
[InlineData(65536)]
public async Task ConnectAsync_IPAddresses_InvalidPort_Throws_ArgumentOutOfRange(int port)
{
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => GetSocket().ConnectAsync(new[] { IPAddress.Loopback }, port));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
socket.Listen(1);
Assert.Throws<InvalidOperationException>(() => { socket.ConnectAsync(new[] { IPAddress.Loopback }, 1); });
await Assert.ThrowsAsync<InvalidOperationException>(() => socket.ConnectAsync(new[] { IPAddress.Loopback }, 1));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

}

if (usesApm)
if (UsesApm)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception thrown by the Task ConnectAsync methods has changed. The exceptions are now consistent with other Task-returning Socket methods.

@tmds

tmds commented Apr 6, 2020

Copy link
Copy Markdown
MemberAuthor

With #33674 merged, I've rebased this PR.

I've added some comments with the test changes that indicate changed behavior.

@stephentoubstephentoub left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Tom.

@stephentoub
stephentoub merged commit eab1d28 into dotnet:masterApr 27, 2020
@karelzkarelz added this to the 5.0.0 milestone Aug 18, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@tmds@stephentoub@antonfirsov@karelz@MihaZupan@Dotnet-GitSync-Bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs - #787

Merged
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync
Apr 27, 2020
Merged

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs#787
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync

Conversation

@tmds

@tmdstmds commented Dec 12, 2019

Copy link
Copy Markdown
Member

No description provided.

@tmds
tmds marked this pull request as ready for review December 12, 2019 09:03
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl @stephentoub this PR is not finished but I'd like some early feedback.
And, some of the test failures I get don't make sense to me (yet).

It seems github doesn't allow me to mark this as Draft and still do a CI run. Can you please mark this as no-merge?

@tmdstmds changed the title Refactor Task SocketAsync.ConnectAsync methods to use AwaitableSocketAsyncEventArgsRefactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgsDec 12, 2019
@tmds
tmdsforce-pushed the socket_connectasync branch from 749388f to ffcc63aCompareDecember 12, 2019 09:07
@MihaZupanMihaZupan added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Dec 12, 2019
@stephentoub

Copy link
Copy Markdown
Member

Thanks, @tmds. I'm concerned about doing something like this until https://github.com/dotnet/corefx/issues/39466 is addressed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@stephentoub

Copy link
Copy Markdown
Member

I'm concerned about doing something like this until dotnet/corefx#39466 is addressed.

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Comment threadsrc/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs Outdated
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Yes, it's on the Socket where it was used to Connect, so not keeping another Socket alive.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@scalablecory
scalablecory requested a review from a teamDecember 15, 2019 01:05
@stephentoubstephentoub removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jan 6, 2020
@stephentoub

Copy link
Copy Markdown
Member

@tmds, some of these test failures look relevant.

@tmds

tmds commented Jan 15, 2020

Copy link
Copy Markdown
MemberAuthor

This test is now failing on Windows:

[Fact]publicasyncTaskCtor_NotStream_ThrowsIOException(){using(Socketlistener=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp))using(Socketclient=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp)){listener.Bind(newIPEndPoint(IPAddress.Loopback,0));awaitclient.ConnectAsync(newIPEndPoint(IPAddress.Loopback,((IPEndPoint)listener.LocalEndPoint).Port));Assert.Throws<IOException>(()=>newNetworkStream(client));}}

Instead of throwing at the expected location, it's throwing on the ConnectAsync call above:

System.Net.Sockets.SocketException : An invalid argument was supplied.
 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/

I'm missing the fallback for connectionless protocols that is part of BeginConnect:

internalIAsyncResultUnsafeBeginConnect(EndPointremoteEP,AsyncCallbackcallback,objectstate,boolflowContext=false)
{
if(CanUseConnectEx(remoteEP))
{
returnBeginConnectEx(remoteEP,flowContext,callback,state);
}
EndPointendPointSnapshot=remoteEP;
varasyncResult=newConnectAsyncResult(this,endPointSnapshot,state,callback);
// For connectionless protocols, Connect is not an I/O call.
Connect(remoteEP);
asyncResult.FinishPostingAsyncOp();
// Synchronously complete the I/O and call the user's callback.
asyncResult.InvokeCallback();
returnasyncResult;
}

I'll add this and check if there are other things which may be missing.

@stephentoub

Copy link
Copy Markdown
Member

Thanks.

@tmds
tmdsforce-pushed the socket_connectasync branch from 4745f62 to 6404854CompareJanuary 30, 2020 13:57
@tmds

tmds commented Feb 10, 2020

Copy link
Copy Markdown
MemberAuthor

The latest change was to change ConnectAsync(SocketAsyncEventArgs) to make it work for UDP sockets. On Windows, the implementation was calling ConnectEx, but that isn't UDP compatible, so WSAConnect is now called instead:

if(CanUseConnectEx(endPointSnapshot)){socketError=e.DoOperationConnectEx(this,_handle);}else{// For connectionless protocols, Connect is not an I/O call.socketError=e.DoOperationConnect(this,_handle);}

I'm not sure if all parts of the CanUseConnectEx check apply here,. It does put us on the WSAConnect way, since the error message has changed:

System.Net.Sockets.SocketException : A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

with stacktrace

 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs:line 400
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/C

From the error message I'd guess WSAENOTCONN is returned by WSAConnect, but that doesn't show up on the WSAConnect doc page. I'm lost.

I don't have a Windows machine to debug.
@dotnet/ncl can someone help me make this work on Windows?

@tmds

tmds commented Feb 11, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@karelz can someone help me with this?

@tmds

tmds commented Feb 27, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@antonfirsov maybe you can have a look?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds your assumption was correct, CanUseConnectEx(...) does not return the right result on SocketAsyncEventArgs path, therefore ConnectEx is being called instead of WSAConnect.

This is even worse on master, since the original SocketAsyncEventArgs code path doesn't even try to check if it can use ConnectEx. The following code fails, which is a bug:

stringpath=Path.Combine(Path.GetTempPath(),Path.GetRandomFileName());varendPoint=newUnixDomainSocketEndPoint(path);usingvarserver=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);usingvarclient=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);server.Bind(endPoint);server.Listen(1);usingvarmre=newManualResetEventSlim(false);usingvarsea=newSocketAsyncEventArgs(){RemoteEndPoint=endPoint};sea.Completed+=(_,__)=>mre.Set();if(client.ConnectAsync(sea))mre.Wait();Assert.Equal(SocketError.Success,sea.SocketError);

@stephentoub I wonder if I should create a separate issue for this or should we just add the fix to this PR for the sake of simplicity?

@antonfirsov

antonfirsov commented Feb 27, 2020

Copy link
Copy Markdown
Contributor

A possible fix on my branch:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs#L3753-L3779

I had to change the expected exception for the test case to ConnectionRefused. The original code was returning InvalidArgument because of the bug:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs#L107-L130

My branch is also in sync with the current master, fixed two minor conflicts from #32675. @tmds can I update this PR with all these changes?

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

@stephentoub

stephentoub commented Feb 27, 2020

Copy link
Copy Markdown
Member

I wonder if I should create a separate issue for this

My preference would be to keep the bug fix and refactoring separate, ideally two PRs, but it could be two commits we don't squash if necessary.

@tmds

tmds commented Mar 2, 2020

Copy link
Copy Markdown
MemberAuthor

Thanks for having a look @antonfirsov! I hope Windows CI will now pass.

ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds a few points:

The Windows build is still failing in SocketAddress.Windows, you need _socketAddress!.Bufferhere.


Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

Have you also tried to address this?


ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

This means that we should enable this test now on Windows.

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

@tmds

tmds commented Mar 3, 2020

Copy link
Copy Markdown
MemberAuthor

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

I'll rewrite the PR in 2 commits when it compiles and tests pass.

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:

This is another Windows-specific problem? Can you take a look?

I wonder what the SocketError is in DoOperationConnect? Is it NotConnected?

internalunsafeSocketErrorDoOperationConnect(Socketsocket,SafeSocketHandlehandle)
{
// Called for connectionless protocols.
SocketErrorsocketError=SocketPal.Connect(handle,_socketAddress.Buffer,_socketAddress.Size);
FinishOperationSync(socketError,0,SocketFlags.None);
returnsocketError;
}

@tmds

tmds commented Mar 10, 2020

Copy link
Copy Markdown
MemberAuthor

@antonfirsov can you take a look at the remaining Windows issue?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds sure, was planning to do so today.

@antonfirsov

antonfirsov commented Mar 11, 2020

Copy link
Copy Markdown
Contributor

@tmds congratulations, you found another Windows-specific bug without using Windows!

Explanation + possible fix + relevant test case here.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

Explanation + possible fix + relevant test case here.

Thank you @antonfirsov ! I have included these changes. When CI passes, I will put UDP Connect(saea) into a separate PR.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

CI shows unrelated test failures in System.Reflection.Tests.TypeTests on mono.

And System.Net.Mail.Functional.Tests has an issue on netcoreapp5.0-Windows_NT-Release-x86-CoreCLR_release-Windows.10.Amd64.Server19H1.ES.Open:

Executed on a000HEL
C:\h\w\AEAD0979\w\AC6B091D\e>call RunTests.cmd --runtime-path C:\h\w\AEAD0979\p ----- start 17/03/2020 9:20:22,26 =============== To repro directly: ===================================================== pushd C:\h\w\AEAD0979\w\AC6B091D\e\
"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests popd
===========================================================================================================
C:\h\w\AEAD0979\w\AC6B091D\e>"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests Discovering: System.Net.Mail.Functional.Tests (method display = ClassAndMethod, method display options = None)
Discovered: System.Net.Mail.Functional.Tests (found 150 of 151 test cases)
Starting: System.Net.Mail.Functional.Tests (parallel test collections = on, max threads = 2)
----- end 17/03/2020 9:20:45,71 ----- exit code -1073740791 ----------------------------------------------------------
17/03/2020- 9:20:45,71
17/03/2020- 9:20:46,02
2020-03-17 09:20:46,477: INFO: 7880: run(82): main: Main thread starting 10 workers
Worker 0: starting...
Worker 1: starting...
Worker 2: starting...
Worker 3: starting...
Worker 4: starting...
Worker 5: starting...
Worker 6: starting...
Worker 7: starting...
Worker 8: starting...
Worker 9: starting...
2020-03-17 09:20:46,493: INFO: 7880: run(89): main: Beginning reading of test results.
2020-03-17 09:20:46,493: INFO: 7880: run(95): main: Uploading results in batches of size 1000
2020-03-17 09:20:46,493: INFO: 7880: run(100): main: Main thread finished queueing batches
2020-03-17 09:20:46,493: INFO: 7880: run(104): main: Main thread exiting
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e\..' for log files
Found log 'C:\h\w\AEAD0979\w\AC6B091D\e\..\console.f0a3d26b.log'
Uri 'https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D'
Generated log list: console.f0a3d26b.log:
https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e' for test results files
No results file found in any of the following formats: xunit, junit, trx
17/03/2020- 9:20:46,52
2020-03-17T09:20:47.212Z	ERROR xunit-reporter.py	xunit-reporter(80)	main	Unable to report xunit results: no test results xml file found.

with dump file: https://helix.dot.net/api/2019-06-17/jobs/b2b1e078-c6e7-4162-8f3f-c9c1d8e8300d/workitems/System.Net.Mail.Functional.Tests/files/dotnet.exe.8892.dmp

@tmds
tmdsforce-pushed the socket_connectasync branch from c0f2b7a to e5d3ed1CompareApril 6, 2020 15:57
[InlineData(65536)]
public async Task ConnectAsync_IPAddresses_InvalidPort_Throws_ArgumentOutOfRange(int port)
{
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => GetSocket().ConnectAsync(new[] { IPAddress.Loopback }, port));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
socket.Listen(1);
Assert.Throws<InvalidOperationException>(() => { socket.ConnectAsync(new[] { IPAddress.Loopback }, 1); });
await Assert.ThrowsAsync<InvalidOperationException>(() => socket.ConnectAsync(new[] { IPAddress.Loopback }, 1));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

}

if (usesApm)
if (UsesApm)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception thrown by the Task ConnectAsync methods has changed. The exceptions are now consistent with other Task-returning Socket methods.

@tmds

tmds commented Apr 6, 2020

Copy link
Copy Markdown
MemberAuthor

With #33674 merged, I've rebased this PR.

I've added some comments with the test changes that indicate changed behavior.

@stephentoubstephentoub left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Tom.

@stephentoub
stephentoub merged commit eab1d28 into dotnet:masterApr 27, 2020
@karelzkarelz added this to the 5.0.0 milestone Aug 18, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@tmds@stephentoub@antonfirsov@karelz@MihaZupan@Dotnet-GitSync-Bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs - #787

Merged
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync
Apr 27, 2020
Merged

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs#787
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync

Conversation

@tmds

@tmdstmds commented Dec 12, 2019

Copy link
Copy Markdown
Member

No description provided.

@tmds
tmds marked this pull request as ready for review December 12, 2019 09:03
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl @stephentoub this PR is not finished but I'd like some early feedback.
And, some of the test failures I get don't make sense to me (yet).

It seems github doesn't allow me to mark this as Draft and still do a CI run. Can you please mark this as no-merge?

@tmdstmds changed the title Refactor Task SocketAsync.ConnectAsync methods to use AwaitableSocketAsyncEventArgsRefactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgsDec 12, 2019
@tmds
tmdsforce-pushed the socket_connectasync branch from 749388f to ffcc63aCompareDecember 12, 2019 09:07
@MihaZupanMihaZupan added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Dec 12, 2019
@stephentoub

Copy link
Copy Markdown
Member

Thanks, @tmds. I'm concerned about doing something like this until https://github.com/dotnet/corefx/issues/39466 is addressed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@stephentoub

Copy link
Copy Markdown
Member

I'm concerned about doing something like this until dotnet/corefx#39466 is addressed.

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Comment threadsrc/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs Outdated
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Yes, it's on the Socket where it was used to Connect, so not keeping another Socket alive.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@scalablecory
scalablecory requested a review from a teamDecember 15, 2019 01:05
@stephentoubstephentoub removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jan 6, 2020
@stephentoub

Copy link
Copy Markdown
Member

@tmds, some of these test failures look relevant.

@tmds

tmds commented Jan 15, 2020

Copy link
Copy Markdown
MemberAuthor

This test is now failing on Windows:

[Fact]publicasyncTaskCtor_NotStream_ThrowsIOException(){using(Socketlistener=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp))using(Socketclient=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp)){listener.Bind(newIPEndPoint(IPAddress.Loopback,0));awaitclient.ConnectAsync(newIPEndPoint(IPAddress.Loopback,((IPEndPoint)listener.LocalEndPoint).Port));Assert.Throws<IOException>(()=>newNetworkStream(client));}}

Instead of throwing at the expected location, it's throwing on the ConnectAsync call above:

System.Net.Sockets.SocketException : An invalid argument was supplied.
 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/

I'm missing the fallback for connectionless protocols that is part of BeginConnect:

internalIAsyncResultUnsafeBeginConnect(EndPointremoteEP,AsyncCallbackcallback,objectstate,boolflowContext=false)
{
if(CanUseConnectEx(remoteEP))
{
returnBeginConnectEx(remoteEP,flowContext,callback,state);
}
EndPointendPointSnapshot=remoteEP;
varasyncResult=newConnectAsyncResult(this,endPointSnapshot,state,callback);
// For connectionless protocols, Connect is not an I/O call.
Connect(remoteEP);
asyncResult.FinishPostingAsyncOp();
// Synchronously complete the I/O and call the user's callback.
asyncResult.InvokeCallback();
returnasyncResult;
}

I'll add this and check if there are other things which may be missing.

@stephentoub

Copy link
Copy Markdown
Member

Thanks.

@tmds
tmdsforce-pushed the socket_connectasync branch from 4745f62 to 6404854CompareJanuary 30, 2020 13:57
@tmds

tmds commented Feb 10, 2020

Copy link
Copy Markdown
MemberAuthor

The latest change was to change ConnectAsync(SocketAsyncEventArgs) to make it work for UDP sockets. On Windows, the implementation was calling ConnectEx, but that isn't UDP compatible, so WSAConnect is now called instead:

if(CanUseConnectEx(endPointSnapshot)){socketError=e.DoOperationConnectEx(this,_handle);}else{// For connectionless protocols, Connect is not an I/O call.socketError=e.DoOperationConnect(this,_handle);}

I'm not sure if all parts of the CanUseConnectEx check apply here,. It does put us on the WSAConnect way, since the error message has changed:

System.Net.Sockets.SocketException : A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

with stacktrace

 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs:line 400
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/C

From the error message I'd guess WSAENOTCONN is returned by WSAConnect, but that doesn't show up on the WSAConnect doc page. I'm lost.

I don't have a Windows machine to debug.
@dotnet/ncl can someone help me make this work on Windows?

@tmds

tmds commented Feb 11, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@karelz can someone help me with this?

@tmds

tmds commented Feb 27, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@antonfirsov maybe you can have a look?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds your assumption was correct, CanUseConnectEx(...) does not return the right result on SocketAsyncEventArgs path, therefore ConnectEx is being called instead of WSAConnect.

This is even worse on master, since the original SocketAsyncEventArgs code path doesn't even try to check if it can use ConnectEx. The following code fails, which is a bug:

stringpath=Path.Combine(Path.GetTempPath(),Path.GetRandomFileName());varendPoint=newUnixDomainSocketEndPoint(path);usingvarserver=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);usingvarclient=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);server.Bind(endPoint);server.Listen(1);usingvarmre=newManualResetEventSlim(false);usingvarsea=newSocketAsyncEventArgs(){RemoteEndPoint=endPoint};sea.Completed+=(_,__)=>mre.Set();if(client.ConnectAsync(sea))mre.Wait();Assert.Equal(SocketError.Success,sea.SocketError);

@stephentoub I wonder if I should create a separate issue for this or should we just add the fix to this PR for the sake of simplicity?

@antonfirsov

antonfirsov commented Feb 27, 2020

Copy link
Copy Markdown
Contributor

A possible fix on my branch:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs#L3753-L3779

I had to change the expected exception for the test case to ConnectionRefused. The original code was returning InvalidArgument because of the bug:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs#L107-L130

My branch is also in sync with the current master, fixed two minor conflicts from #32675. @tmds can I update this PR with all these changes?

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

@stephentoub

stephentoub commented Feb 27, 2020

Copy link
Copy Markdown
Member

I wonder if I should create a separate issue for this

My preference would be to keep the bug fix and refactoring separate, ideally two PRs, but it could be two commits we don't squash if necessary.

@tmds

tmds commented Mar 2, 2020

Copy link
Copy Markdown
MemberAuthor

Thanks for having a look @antonfirsov! I hope Windows CI will now pass.

ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds a few points:

The Windows build is still failing in SocketAddress.Windows, you need _socketAddress!.Bufferhere.


Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

Have you also tried to address this?


ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

This means that we should enable this test now on Windows.

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

@tmds

tmds commented Mar 3, 2020

Copy link
Copy Markdown
MemberAuthor

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

I'll rewrite the PR in 2 commits when it compiles and tests pass.

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:

This is another Windows-specific problem? Can you take a look?

I wonder what the SocketError is in DoOperationConnect? Is it NotConnected?

internalunsafeSocketErrorDoOperationConnect(Socketsocket,SafeSocketHandlehandle)
{
// Called for connectionless protocols.
SocketErrorsocketError=SocketPal.Connect(handle,_socketAddress.Buffer,_socketAddress.Size);
FinishOperationSync(socketError,0,SocketFlags.None);
returnsocketError;
}

@tmds

tmds commented Mar 10, 2020

Copy link
Copy Markdown
MemberAuthor

@antonfirsov can you take a look at the remaining Windows issue?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds sure, was planning to do so today.

@antonfirsov

antonfirsov commented Mar 11, 2020

Copy link
Copy Markdown
Contributor

@tmds congratulations, you found another Windows-specific bug without using Windows!

Explanation + possible fix + relevant test case here.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

Explanation + possible fix + relevant test case here.

Thank you @antonfirsov ! I have included these changes. When CI passes, I will put UDP Connect(saea) into a separate PR.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

CI shows unrelated test failures in System.Reflection.Tests.TypeTests on mono.

And System.Net.Mail.Functional.Tests has an issue on netcoreapp5.0-Windows_NT-Release-x86-CoreCLR_release-Windows.10.Amd64.Server19H1.ES.Open:

Executed on a000HEL
C:\h\w\AEAD0979\w\AC6B091D\e>call RunTests.cmd --runtime-path C:\h\w\AEAD0979\p ----- start 17/03/2020 9:20:22,26 =============== To repro directly: ===================================================== pushd C:\h\w\AEAD0979\w\AC6B091D\e\
"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests popd
===========================================================================================================
C:\h\w\AEAD0979\w\AC6B091D\e>"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests Discovering: System.Net.Mail.Functional.Tests (method display = ClassAndMethod, method display options = None)
Discovered: System.Net.Mail.Functional.Tests (found 150 of 151 test cases)
Starting: System.Net.Mail.Functional.Tests (parallel test collections = on, max threads = 2)
----- end 17/03/2020 9:20:45,71 ----- exit code -1073740791 ----------------------------------------------------------
17/03/2020- 9:20:45,71
17/03/2020- 9:20:46,02
2020-03-17 09:20:46,477: INFO: 7880: run(82): main: Main thread starting 10 workers
Worker 0: starting...
Worker 1: starting...
Worker 2: starting...
Worker 3: starting...
Worker 4: starting...
Worker 5: starting...
Worker 6: starting...
Worker 7: starting...
Worker 8: starting...
Worker 9: starting...
2020-03-17 09:20:46,493: INFO: 7880: run(89): main: Beginning reading of test results.
2020-03-17 09:20:46,493: INFO: 7880: run(95): main: Uploading results in batches of size 1000
2020-03-17 09:20:46,493: INFO: 7880: run(100): main: Main thread finished queueing batches
2020-03-17 09:20:46,493: INFO: 7880: run(104): main: Main thread exiting
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e\..' for log files
Found log 'C:\h\w\AEAD0979\w\AC6B091D\e\..\console.f0a3d26b.log'
Uri 'https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D'
Generated log list: console.f0a3d26b.log:
https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e' for test results files
No results file found in any of the following formats: xunit, junit, trx
17/03/2020- 9:20:46,52
2020-03-17T09:20:47.212Z	ERROR xunit-reporter.py	xunit-reporter(80)	main	Unable to report xunit results: no test results xml file found.

with dump file: https://helix.dot.net/api/2019-06-17/jobs/b2b1e078-c6e7-4162-8f3f-c9c1d8e8300d/workitems/System.Net.Mail.Functional.Tests/files/dotnet.exe.8892.dmp

@tmds
tmdsforce-pushed the socket_connectasync branch from c0f2b7a to e5d3ed1CompareApril 6, 2020 15:57
[InlineData(65536)]
public async Task ConnectAsync_IPAddresses_InvalidPort_Throws_ArgumentOutOfRange(int port)
{
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => GetSocket().ConnectAsync(new[] { IPAddress.Loopback }, port));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
socket.Listen(1);
Assert.Throws<InvalidOperationException>(() => { socket.ConnectAsync(new[] { IPAddress.Loopback }, 1); });
await Assert.ThrowsAsync<InvalidOperationException>(() => socket.ConnectAsync(new[] { IPAddress.Loopback }, 1));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

}

if (usesApm)
if (UsesApm)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception thrown by the Task ConnectAsync methods has changed. The exceptions are now consistent with other Task-returning Socket methods.

@tmds

tmds commented Apr 6, 2020

Copy link
Copy Markdown
MemberAuthor

With #33674 merged, I've rebased this PR.

I've added some comments with the test changes that indicate changed behavior.

@stephentoubstephentoub left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Tom.

@stephentoub
stephentoub merged commit eab1d28 into dotnet:masterApr 27, 2020
@karelzkarelz added this to the 5.0.0 milestone Aug 18, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@tmds@stephentoub@antonfirsov@karelz@MihaZupan@Dotnet-GitSync-Bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs - #787

Merged
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync
Apr 27, 2020
Merged

Refactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgs#787
stephentoub merged 2 commits into
dotnet:masterfrom
tmds:socket_connectasync

Conversation

@tmds

@tmdstmds commented Dec 12, 2019

Copy link
Copy Markdown
Member

No description provided.

@tmds
tmds marked this pull request as ready for review December 12, 2019 09:03
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl @stephentoub this PR is not finished but I'd like some early feedback.
And, some of the test failures I get don't make sense to me (yet).

It seems github doesn't allow me to mark this as Draft and still do a CI run. Can you please mark this as no-merge?

@tmdstmds changed the title Refactor Task SocketAsync.ConnectAsync methods to use AwaitableSocketAsyncEventArgsRefactor Task Socket.ConnectAsync methods to use AwaitableSocketAsyncEventArgsDec 12, 2019
@tmds
tmdsforce-pushed the socket_connectasync branch from 749388f to ffcc63aCompareDecember 12, 2019 09:07
@MihaZupanMihaZupan added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Dec 12, 2019
@stephentoub

Copy link
Copy Markdown
Member

Thanks, @tmds. I'm concerned about doing something like this until https://github.com/dotnet/corefx/issues/39466 is addressed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@stephentoub

Copy link
Copy Markdown
Member

I'm concerned about doing something like this until dotnet/corefx#39466 is addressed.

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Comment threadsrc/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs Outdated
@tmds

tmds commented Dec 12, 2019

Copy link
Copy Markdown
MemberAuthor

Although, looking at the change in more detail now, it seems you're not reusing the SAEA across sockets, only using it for that one socket? In which case maybe this isn't a big deal, because the SAEA will only be storing the same socket that it's being used with?

Yes, it's on the Socket where it was used to Connect, so not keeping another Socket alive.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Outdated
@scalablecory
scalablecory requested a review from a teamDecember 15, 2019 01:05
@stephentoubstephentoub removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jan 6, 2020
@stephentoub

Copy link
Copy Markdown
Member

@tmds, some of these test failures look relevant.

@tmds

tmds commented Jan 15, 2020

Copy link
Copy Markdown
MemberAuthor

This test is now failing on Windows:

[Fact]publicasyncTaskCtor_NotStream_ThrowsIOException(){using(Socketlistener=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp))using(Socketclient=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp)){listener.Bind(newIPEndPoint(IPAddress.Loopback,0));awaitclient.ConnectAsync(newIPEndPoint(IPAddress.Loopback,((IPEndPoint)listener.LocalEndPoint).Port));Assert.Throws<IOException>(()=>newNetworkStream(client));}}

Instead of throwing at the expected location, it's throwing on the ConnectAsync call above:

System.Net.Sockets.SocketException : An invalid argument was supplied.
 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/

I'm missing the fallback for connectionless protocols that is part of BeginConnect:

internalIAsyncResultUnsafeBeginConnect(EndPointremoteEP,AsyncCallbackcallback,objectstate,boolflowContext=false)
{
if(CanUseConnectEx(remoteEP))
{
returnBeginConnectEx(remoteEP,flowContext,callback,state);
}
EndPointendPointSnapshot=remoteEP;
varasyncResult=newConnectAsyncResult(this,endPointSnapshot,state,callback);
// For connectionless protocols, Connect is not an I/O call.
Connect(remoteEP);
asyncResult.FinishPostingAsyncOp();
// Synchronously complete the I/O and call the user's callback.
asyncResult.InvokeCallback();
returnasyncResult;
}

I'll add this and check if there are other things which may be missing.

@stephentoub

Copy link
Copy Markdown
Member

Thanks.

@tmds
tmdsforce-pushed the socket_connectasync branch from 4745f62 to 6404854CompareJanuary 30, 2020 13:57
@tmds

tmds commented Feb 10, 2020

Copy link
Copy Markdown
MemberAuthor

The latest change was to change ConnectAsync(SocketAsyncEventArgs) to make it work for UDP sockets. On Windows, the implementation was calling ConnectEx, but that isn't UDP compatible, so WSAConnect is now called instead:

if(CanUseConnectEx(endPointSnapshot)){socketError=e.DoOperationConnectEx(this,_handle);}else{// For connectionless protocols, Connect is not an I/O call.socketError=e.DoOperationConnect(this,_handle);}

I'm not sure if all parts of the CanUseConnectEx check apply here,. It does put us on the WSAConnect way, since the error message has changed:

System.Net.Sockets.SocketException : A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

with stacktrace

 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 1147
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 974
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs:line 132
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, EndPoint remoteEP) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.cs:line 19
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException() in /_/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs:line 41
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Net.Sockets.Tests.NetworkStreamTest.Ctor_NotStream_ThrowsIOException()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs:line 400
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs:line 42
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/C

From the error message I'd guess WSAENOTCONN is returned by WSAConnect, but that doesn't show up on the WSAConnect doc page. I'm lost.

I don't have a Windows machine to debug.
@dotnet/ncl can someone help me make this work on Windows?

@tmds

tmds commented Feb 11, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@karelz can someone help me with this?

@tmds

tmds commented Feb 27, 2020

Copy link
Copy Markdown
MemberAuthor

@dotnet/ncl can someone help me make this work on Windows?

@antonfirsov maybe you can have a look?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds your assumption was correct, CanUseConnectEx(...) does not return the right result on SocketAsyncEventArgs path, therefore ConnectEx is being called instead of WSAConnect.

This is even worse on master, since the original SocketAsyncEventArgs code path doesn't even try to check if it can use ConnectEx. The following code fails, which is a bug:

stringpath=Path.Combine(Path.GetTempPath(),Path.GetRandomFileName());varendPoint=newUnixDomainSocketEndPoint(path);usingvarserver=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);usingvarclient=newSocket(AddressFamily.Unix,SocketType.Stream,ProtocolType.Unspecified);server.Bind(endPoint);server.Listen(1);usingvarmre=newManualResetEventSlim(false);usingvarsea=newSocketAsyncEventArgs(){RemoteEndPoint=endPoint};sea.Completed+=(_,__)=>mre.Set();if(client.ConnectAsync(sea))mre.Wait();Assert.Equal(SocketError.Success,sea.SocketError);

@stephentoub I wonder if I should create a separate issue for this or should we just add the fix to this PR for the sake of simplicity?

@antonfirsov

antonfirsov commented Feb 27, 2020

Copy link
Copy Markdown
Contributor

A possible fix on my branch:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs#L3753-L3779

I had to change the expected exception for the test case to ConnectionRefused. The original code was returning InvalidArgument because of the bug:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs#L107-L130

My branch is also in sync with the current master, fixed two minor conflicts from #32675. @tmds can I update this PR with all these changes?

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

@stephentoub

stephentoub commented Feb 27, 2020

Copy link
Copy Markdown
Member

I wonder if I should create a separate issue for this

My preference would be to keep the bug fix and refactoring separate, ideally two PRs, but it could be two commits we don't squash if necessary.

@tmds

tmds commented Mar 2, 2020

Copy link
Copy Markdown
MemberAuthor

Thanks for having a look @antonfirsov! I hope Windows CI will now pass.

ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds a few points:

The Windows build is still failing in SocketAddress.Windows, you need _socketAddress!.Bufferhere.


Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:
https://github.com/antonfirsov/runtime/blob/socket_connectasync-af/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs#L970

Have you also tried to address this?


ConnectAsync(saea) did not support non-stream protocols (not supported by Windows ConnectEx). With the refactoring, the Task-based API calls ConnectAsync(saea), so it needs to work also for the non-stream protocols.

This means that we should enable this test now on Windows.

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

@tmds

tmds commented Mar 3, 2020

Copy link
Copy Markdown
MemberAuthor

Additionally, I was unable to find any confirmation for the old behavior in our docs, which supports my argument that this was simply a bug. Any chance you can create a separate bugfix PR as @stephentoub suggested?

I'll rewrite the PR in 2 commits when it compiles and tests pass.

Note that Ctor_NotStream_ThrowsIOException still fails, because Socket.SocketError is NotConnected on this line, despite of the succesful connect returning synchronously:

This is another Windows-specific problem? Can you take a look?

I wonder what the SocketError is in DoOperationConnect? Is it NotConnected?

internalunsafeSocketErrorDoOperationConnect(Socketsocket,SafeSocketHandlehandle)
{
// Called for connectionless protocols.
SocketErrorsocketError=SocketPal.Connect(handle,_socketAddress.Buffer,_socketAddress.Size);
FinishOperationSync(socketError,0,SocketFlags.None);
returnsocketError;
}

@tmds

tmds commented Mar 10, 2020

Copy link
Copy Markdown
MemberAuthor

@antonfirsov can you take a look at the remaining Windows issue?

@antonfirsov

Copy link
Copy Markdown
Contributor

@tmds sure, was planning to do so today.

@antonfirsov

antonfirsov commented Mar 11, 2020

Copy link
Copy Markdown
Contributor

@tmds congratulations, you found another Windows-specific bug without using Windows!

Explanation + possible fix + relevant test case here.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

Explanation + possible fix + relevant test case here.

Thank you @antonfirsov ! I have included these changes. When CI passes, I will put UDP Connect(saea) into a separate PR.

@tmds

tmds commented Mar 17, 2020

Copy link
Copy Markdown
MemberAuthor

CI shows unrelated test failures in System.Reflection.Tests.TypeTests on mono.

And System.Net.Mail.Functional.Tests has an issue on netcoreapp5.0-Windows_NT-Release-x86-CoreCLR_release-Windows.10.Amd64.Server19H1.ES.Open:

Executed on a000HEL
C:\h\w\AEAD0979\w\AC6B091D\e>call RunTests.cmd --runtime-path C:\h\w\AEAD0979\p ----- start 17/03/2020 9:20:22,26 =============== To repro directly: ===================================================== pushd C:\h\w\AEAD0979\w\AC6B091D\e\
"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests popd
===========================================================================================================
C:\h\w\AEAD0979\w\AC6B091D\e>"C:\h\w\AEAD0979\p\dotnet.exe" exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -nocolor -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing -notrait category=nonnetcoreapptests -notrait category=nonwindowstests Discovering: System.Net.Mail.Functional.Tests (method display = ClassAndMethod, method display options = None)
Discovered: System.Net.Mail.Functional.Tests (found 150 of 151 test cases)
Starting: System.Net.Mail.Functional.Tests (parallel test collections = on, max threads = 2)
----- end 17/03/2020 9:20:45,71 ----- exit code -1073740791 ----------------------------------------------------------
17/03/2020- 9:20:45,71
17/03/2020- 9:20:46,02
2020-03-17 09:20:46,477: INFO: 7880: run(82): main: Main thread starting 10 workers
Worker 0: starting...
Worker 1: starting...
Worker 2: starting...
Worker 3: starting...
Worker 4: starting...
Worker 5: starting...
Worker 6: starting...
Worker 7: starting...
Worker 8: starting...
Worker 9: starting...
2020-03-17 09:20:46,493: INFO: 7880: run(89): main: Beginning reading of test results.
2020-03-17 09:20:46,493: INFO: 7880: run(95): main: Uploading results in batches of size 1000
2020-03-17 09:20:46,493: INFO: 7880: run(100): main: Main thread finished queueing batches
2020-03-17 09:20:46,493: INFO: 7880: run(104): main: Main thread exiting
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e\..' for log files
Found log 'C:\h\w\AEAD0979\w\AC6B091D\e\..\console.f0a3d26b.log'
Uri 'https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D'
Generated log list: console.f0a3d26b.log:
https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-787-merge-b2b1e078c6e741628f/System.Net.Mail.Functional.Tests/console.f0a3d26b.log?sv=2019-02-02&se=2020-03-27T09%3A19%3A56Z&sr=c&sp=rl&sig=lHu%2BbJDr%2Bei8G72cXctXt6vZgiegq3wqWLRAYK43ujM%3D
Searching 'C:\h\w\AEAD0979\w\AC6B091D\e' for test results files
No results file found in any of the following formats: xunit, junit, trx
17/03/2020- 9:20:46,52
2020-03-17T09:20:47.212Z	ERROR xunit-reporter.py	xunit-reporter(80)	main	Unable to report xunit results: no test results xml file found.

with dump file: https://helix.dot.net/api/2019-06-17/jobs/b2b1e078-c6e7-4162-8f3f-c9c1d8e8300d/workitems/System.Net.Mail.Functional.Tests/files/dotnet.exe.8892.dmp

@tmds
tmdsforce-pushed the socket_connectasync branch from c0f2b7a to e5d3ed1CompareApril 6, 2020 15:57
[InlineData(65536)]
public async Task ConnectAsync_IPAddresses_InvalidPort_Throws_ArgumentOutOfRange(int port)
{
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => GetSocket().ConnectAsync(new[] { IPAddress.Loopback }, port));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
socket.Listen(1);
Assert.Throws<InvalidOperationException>(() => { socket.ConnectAsync(new[] { IPAddress.Loopback }, 1); });
await Assert.ThrowsAsync<InvalidOperationException>(() => socket.ConnectAsync(new[] { IPAddress.Loopback }, 1));

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires await to throw. The check could be added in the Task ConnectAsync directly.

}

if (usesApm)
if (UsesApm)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception thrown by the Task ConnectAsync methods has changed. The exceptions are now consistent with other Task-returning Socket methods.

@tmds

tmds commented Apr 6, 2020

Copy link
Copy Markdown
MemberAuthor

With #33674 merged, I've rebased this PR.

I've added some comments with the test changes that indicate changed behavior.

@stephentoubstephentoub left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Tom.

@stephentoub
stephentoub merged commit eab1d28 into dotnet:masterApr 27, 2020
@karelzkarelz added this to the 5.0.0 milestone Aug 18, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@tmds@stephentoub@antonfirsov@karelz@MihaZupan@Dotnet-GitSync-Bot