Uh oh!
There was an error while loading. Please reload this page.
Add cache for Socket.LocalEndPoint - #39313
Conversation
ghost
commented
Jul 14, 2020
Tagging subscribers to this area: @dotnet/ncl |
CarnaViire
commented
Jul 16, 2020
/azp run runtime-libraries outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
CarnaViire
commented
Jul 24, 2020
/azp run runtime-libraries outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
karelz
left a comment
There was a problem hiding this comment.
LGTM, but I let @antonfirsov make the final ok ;)
Uh oh!
There was an error while loading. Please reload this page.
I'm concerned if we should maybe reset runtime/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Lines 2685 to 2712 in f8e92ec If I'm not missing anything there will be no user callback querying Such a call may enforce caching a wrong value for @tmds maybe you have some thoughts on this? |
CarnaViire
commented
Jul 28, 2020
@antonfirsov Here is a list of all changes of _rightEndPoint that I have found in the code (sorry for the long list, I would put it under cut if I knew how)
You suggest to clear _localEndPoint on the reset of _rightEndPoint, which are items 2. and 3. on the list. If we look at subitems of item 1., we can see that most of them are if _rightEndPoint was null before or in the constructor, which means if we clear _localEndPoint at this time we won't actually change anything. And a change of _rightEndPoint after non-blocking connect will only happen once I believe. What I am trying to say is if we want to clear _localEndPoint on the reset of _rightEndPoint, maybe we could actually return to my original proposal of clearing _localEndPoint on every _rightEndPoint change? The only place where it might possibly unnesessary clear some cached value is this non-blocking connect part (item 1.2.) and we might use _rightEndPoint there instead of new property RightEndPoint specifically in this case. |
Uh oh!
There was an error while loading. Please reload this page.
|
Azure Pipelines successfully started running 1 pipeline(s). |
CarnaViire
commented
Aug 19, 2020
/azp run runtime-libraries outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
CarnaViire
commented
Aug 25, 2020
So the behavior with wildcard addresses is as follows.
I added clearing of cached wildcard local endpoints on |
CarnaViire
commented
Aug 25, 2020
/azp run runtime-libraries outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Uh oh!
There was an error while loading. Please reload this page.
CarnaViire
commented
Aug 26, 2020
/azp run runtime-libraries outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
antonfirsov
left a comment
There was a problem hiding this comment.
We need to make sure all independent implementations are covered in the tests, otherwise looks good now.
| [Fact] | ||
| public void UdpSocket_ClientNotBound_LocalEPBecomesWildcardOnSendTo() | ||
| { | ||
| using (Socket server = CreateUdpSocket()) | ||
| using (Socket client = CreateUdpSocket()) | ||
| { | ||
| int serverPort = server.BindToAnonymousPort(Wildcard); | ||
| Assert.Null(client.LocalEndPoint); // null before sendto | ||
| var sendToEP = new IPEndPoint(Loopback, serverPort); | ||
| client.SendTo(new byte[] { 1, 2, 3 }, sendToEP); | ||
| Assert.Equal(Wildcard, GetLocalEPAddress(client)); // wildcard after sendto | ||
| byte[] buf = new byte[3]; | ||
| EndPoint receiveFromEP = new IPEndPoint(Wildcard, 0); | ||
| server.ReceiveFrom(buf, ref receiveFromEP); | ||
| Assert.Equal(new byte[] { 1, 2, 3 }, buf); | ||
| } | ||
| } | ||
| [Fact] | ||
| public void UdpSocket_ClientNotBound_LocalEPBecomesWildcardOnAsyncSendTo() | ||
| { | ||
| using (Socket server = CreateUdpSocket()) | ||
| using (Socket client = CreateUdpSocket()) | ||
| { | ||
| int serverPort = server.BindToAnonymousPort(Wildcard); | ||
| Assert.Null(client.LocalEndPoint); // null before async WSASendTo | ||
| var sendToEP = new IPEndPoint(Loopback, serverPort); | ||
| IAsyncResult sendToResult = client.BeginSendTo(new byte[] { 4, 5, 6 }, 0, 3, SocketFlags.None, sendToEP, null, null); | ||
| sendToResult.AsyncWaitHandle.WaitOne(); | ||
| client.EndSendTo(sendToResult); | ||
| Assert.Equal(Wildcard, GetLocalEPAddress(client)); // wildcard after async WSASendTo | ||
| byte[] buf = new byte[3]; | ||
| EndPoint receiveFromEP = new IPEndPoint(Wildcard, 0); | ||
| server.ReceiveFrom(buf, ref receiveFromEP); | ||
| Assert.Equal(new byte[] { 4, 5, 6 }, buf); | ||
| } | ||
| } |
There was a problem hiding this comment.
These 2 tests seem to test the same thing for two different connect implementations. I suggest dedupe their code and also cover the remaining ones: ConnectAsync(SocketAsyncEventArgs) and SocketTaskExtensions.ConnectAsync(this Socket, ....). For this the best would be to utilize SocketTestHelperBase<T>.
There was a problem hiding this comment.
Rewrote the tests, please check that I understood you correctly :)
Added _localEndPoint field to cache LocalEndPoint value.
Introduced RightEndPoint property to encapsulate clearing _localEndPoint on _rightEndPoint change.Cached value is cleared on connect, error and disconnect.Cached value is cleared on error and disconnect. If the value is a wildcard address, it is also cleared on connect and accept.Fix#1482