Repository: dotnet/runtime
File: src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs (C#)

Code before:
                while (true)
                {
                    DateTime waitStart = DateTime.UtcNow;

                    if (!e.Wait(timeout))
                    {
                        timeoutExpired = true;
                        break;
                    }

                    // Reset the event now to avoid lost notifications if the processing is unsuccessful.
                    e.Reset();

                    // We've been signalled to try to process the operation.
                    OperationResult result = queue.ProcessQueuedOperation(operation);
                    if (result == OperationResult.Completed ||
                        result == OperationResult.Cancelled)
                    {
                        break;
                    }

                    // Couldn't process the operation.
                    // Adjust timeout and try again.
                    if (timeout > 0)
                    {
                        timeout -= (int)(DateTime.UtcNow - waitStart).TotalMilliseconds;

                        if (timeout <= 0)
                        {
                            timeoutExpired = true;
                            break;
                        }
                    }
                }

                if (timeoutExpired)
                {
                    queue.CancelAndContinueProcessing(operation);
                    operation.ErrorCode = SocketError.TimedOut;
                }
            }
        }

        private bool ShouldRetrySyncOperation(out SocketError errorCode)
        {
            if (_isHandleNonBlocking)
            {
                errorCode = SocketError.Success;    // Will be ignored
                return true;
            }


Review comment (suggestion):
Using DateTime.UtcNow to compute elapsed time for a timeout is not monotonic. With the change to TotalMilliseconds, any backward system clock adjustment (e.g., NTP step) will make the elapsed value negative and therefore increase `timeout`, potentially extending the wait far beyond the requested timeout. Prefer a monotonic source like Environment.TickCount64 or Stopwatch to compute elapsed and decrement the remaining timeout (clamping as needed).

Code after:
                while (true)
                {
                    long waitStart = Stopwatch.GetTimestamp();

                    if (!e.Wait(timeout))
                    {
                        timeoutExpired = true;
                        break;
                    }

                    // Reset the event now to avoid lost notifications if the processing is unsuccessful.
                    e.Reset();

                    // We've been signalled to try to process the operation.
                    OperationResult result = queue.ProcessQueuedOperation(operation);
                    if (result == OperationResult.Completed ||
                        result == OperationResult.Cancelled)
                    {
                        break;
                    }

                    // Couldn't process the operation.
                    // Adjust timeout and try again.
                    if (timeout > 0)
                    {
                        timeout -= (int)Stopwatch.GetElapsedTime(waitStart).TotalMilliseconds;

                        if (timeout <= 0)
                        {
                            timeoutExpired = true;
                            break;
                        }
                    }
                }

                if (timeoutExpired)
                {
                    queue.CancelAndContinueProcessing(operation);
                    operation.ErrorCode = SocketError.TimedOut;
                }
            }
        }

        private bool ShouldRetrySyncOperation(out SocketError errorCode)
        {
            if (_isHandleNonBlocking)
            {
                errorCode = SocketError.Success;    // Will be ignored
                return true;
            }