public static bool TryCompleteSendTo(SafeSocketHandle socket, ReadOnlySpan<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)
{
bool successfulSend = false;
+ long start = socket.IsUnderlyingBlocking && socket.SendTimeout > 0 ? Environment.TickCount64 : 0; // Get ticks only if timeout is set and socket is blocking.
+
while (true)
{
int sent;
errorCode = SocketError.Success;
return true;
}
+
+ if (socket.IsUnderlyingBlocking && socket.SendTimeout > 0 && (Environment.TickCount64 - start) >= socket.SendTimeout)
+ {
+ // When socket is truly in blocking mode, we depend on OS to enforce send timeout.
+ // When we are here we had partial send when we neither completed or failed.
+ // If we loop again, OS will wait another configured timeout before returning from system call.
+ // This block check checks is we used all our timer across all iterations.
+ errorCode = SocketError.TimedOut;
+ return true;
+ }
+
}
}
namespace System.Net.Sockets.Tests
{
+ [Collection("NoParallelTests")]
public class TimeoutTest
{
- [OuterLoop] // TODO: Issue #11345
[Fact]
public void GetAndSet_Success()
{
}
}
- [OuterLoop] // TODO: Issue #11345
[Fact]
public void SocketSendTimeout_GetAndSet_Success()
{
// but also not so large that it takes too long to run.
private const int Timeout = 2000;
- [ActiveIssue(23767, TestPlatforms.AnyUnix)]
[OuterLoop] // TODO: Issue #11345
[Theory]
[InlineData(true)]
acceptedSocket.ForceNonBlocking(forceNonBlocking);
- DateTime start = default(DateTime);
+ long start = Environment.TickCount64;
SocketException sockEx = Assert.Throws<SocketException>(() =>
{
- start = DateTime.UtcNow;
acceptedSocket.Receive(new byte[1]);
});
- double elapsed = (DateTime.UtcNow - start).TotalMilliseconds;
-
+ long elapsed = Environment.TickCount64 - start;
Assert.Equal(SocketError.TimedOut, sockEx.SocketErrorCode);
Assert.True(acceptedSocket.Connected);
// Try to ensure that the elapsed timeout is reasonably correct
// Sometimes test machines run slowly
- Assert.InRange(elapsed, Timeout * 0.75, Timeout * 2);
+ Assert.InRange(elapsed, Timeout * 0.75, Timeout * 1.9999);
}
}
acceptedSocket.ForceNonBlocking(forceNonBlocking);
- var sw = new Stopwatch();
+ long start = Environment.TickCount64;
// Force Send to timeout by filling the kernel buffer.
var sendBuffer = new byte[16 * 1024];
{
while (true)
{
- sw.Restart();
+ start = Environment.TickCount64;
acceptedSocket.Send(sendBuffer);
}
}));
- double elapsed = sw.Elapsed.TotalMilliseconds;
-
+ long elapsed = Environment.TickCount64 - start;
Assert.Equal(SocketError.TimedOut, sockEx.SocketErrorCode);
Assert.True(acceptedSocket.Connected);
// Try to ensure that the elapsed timeout is reasonably correct
// Sometimes test machines run slowly
- Assert.InRange(elapsed, Timeout * 0.5, Timeout * 3);
+ Assert.InRange(elapsed, Timeout * 0.75, Timeout * 1.9999);
}
}
}