Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit b48403d

Browse files
tmdsstephentoub
authored andcommitted
Fix return value of partially successful Socket.Send (#24005)
* Fix return value of partially successful Socket.Send * Fix Assert.InRange range * Fix SocketError return * move successfulSend outside loop * Test: buffer size 100M -> 5M * Disable test on Windows because all data gets sent
1 parent 6887d9a commit b48403d

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ public static bool TryCompleteSendTo(SafeCloseSocket socket, IList<ArraySegment<
721721

722722
public static bool TryCompleteSendTo(SafeCloseSocket socket, byte[] buffer, IList<ArraySegment<byte>> buffers, ref int bufferIndex, ref int offset, ref int count, SocketFlags flags, byte[] socketAddress, int socketAddressLen, ref int bytesSent, out SocketError errorCode)
723723
{
724+
bool successfulSend = false;
724725
for (;;)
725726
{
726727
int sent;
@@ -745,16 +746,17 @@ public static bool TryCompleteSendTo(SafeCloseSocket socket, byte[] buffer, ILis
745746

746747
if (sent == -1)
747748
{
748-
if (errno != Interop.Error.EAGAIN && errno != Interop.Error.EWOULDBLOCK)
749+
if (!successfulSend && errno != Interop.Error.EAGAIN && errno != Interop.Error.EWOULDBLOCK)
749750
{
750751
errorCode = GetSocketErrorForErrorCode(errno);
751752
return true;
752753
}
753754

754-
errorCode = SocketError.Success;
755+
errorCode = successfulSend ? SocketError.Success : SocketError.WouldBlock;
755756
return false;
756757
}
757758

759+
successfulSend = true;
758760
bytesSent += sent;
759761

760762
bool isComplete = sent == 0 ||
@@ -902,8 +904,8 @@ public static SocketError Send(SafeCloseSocket handle, IList<ArraySegment<byte>>
902904
int bufferIndex = 0;
903905
int offset = 0;
904906
SocketError errorCode;
905-
bool completed = TryCompleteSendTo(handle, bufferList, ref bufferIndex, ref offset, socketFlags, null, 0, ref bytesTransferred, out errorCode);
906-
return completed ? errorCode : SocketError.WouldBlock;
907+
TryCompleteSendTo(handle, bufferList, ref bufferIndex, ref offset, socketFlags, null, 0, ref bytesTransferred, out errorCode);
908+
return errorCode;
907909
}
908910

909911
public static SocketError Send(SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, out int bytesTransferred)
@@ -915,8 +917,8 @@ public static SocketError Send(SafeCloseSocket handle, byte[] buffer, int offset
915917

916918
bytesTransferred = 0;
917919
SocketError errorCode;
918-
bool completed = TryCompleteSendTo(handle, buffer, ref offset, ref count, socketFlags, null, 0, ref bytesTransferred, out errorCode);
919-
return completed ? errorCode : SocketError.WouldBlock;
920+
TryCompleteSendTo(handle, buffer, ref offset, ref count, socketFlags, null, 0, ref bytesTransferred, out errorCode);
921+
return errorCode;
920922
}
921923

922924
public static SocketError SendFile(SafeCloseSocket handle, FileStream fileStream)
@@ -947,8 +949,8 @@ public static SocketError SendTo(SafeCloseSocket handle, byte[] buffer, int offs
947949

948950
bytesTransferred = 0;
949951
SocketError errorCode;
950-
bool completed = TryCompleteSendTo(handle, buffer, ref offset, ref count, socketFlags, socketAddress, socketAddressLen, ref bytesTransferred, out errorCode);
951-
return completed ? errorCode : SocketError.WouldBlock;
952+
TryCompleteSendTo(handle, buffer, ref offset, ref count, socketFlags, socketAddress, socketAddressLen, ref bytesTransferred, out errorCode);
953+
return errorCode;
952954
}
953955

954956
public static SocketError Receive(SafeCloseSocket handle, IList<ArraySegment<byte>> buffers, ref SocketFlags socketFlags, out int bytesTransferred)

src/System.Net.Sockets/tests/FunctionalTests/SendReceive.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,35 @@ public async Task ReceiveIovMaxUdp_SuccessOrMessageSize()
10281028
Assert.True(receiveTask.IsCompleted);
10291029
await receiveTask;
10301030
}
1031+
1032+
[Fact]
1033+
[PlatformSpecific(~TestPlatforms.Windows)] // All data is sent, even when very large (100M).
1034+
public void SocketSendWouldBlock_ReturnsBytesSent()
1035+
{
1036+
using (var server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
1037+
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
1038+
{
1039+
// listen
1040+
server.BindToAnonymousPort(IPAddress.Loopback);
1041+
server.Listen(1);
1042+
// connect
1043+
client.Connect(server.LocalEndPoint);
1044+
// accept
1045+
using (Socket socket = server.Accept())
1046+
{
1047+
// We send a large amount of data but don't read it.
1048+
// A chunck will be sent, attempts to send more will return SocketError.WouldBlock.
1049+
// Socket.Send must return the success of the partial send.
1050+
socket.Blocking = false;
1051+
var data = new byte[5_000_000];
1052+
SocketError error;
1053+
int bytesSent = socket.Send(data, 0, data.Length, SocketFlags.None, out error);
1054+
1055+
Assert.Equal(SocketError.Success, error);
1056+
Assert.InRange(bytesSent, 1, data.Length - 1);
1057+
}
1058+
}
1059+
}
10311060
}
10321061

10331062
public sealed class SendReceiveUdpClient : MemberDatas

0 commit comments

Comments
 (0)