Skip to content

Commit

Permalink
[7.0] Fix reporting of an async IO timeout error on Windows (`SerialP…
Browse files Browse the repository at this point in the history
…ort`) (#81745)

- Port of #81744
- When an async `SerialPort` IO operation times out, it reports the timeout in the IO completion with an `NTSTATUS` value of `WAIT_TIMEOUT` (258)
- In the thread pool when using `GetQueuedCompletionStatusEx`, the `NTSTATUS` value was being checked against `STATUS_SUCCESS` to determine success, so the `WAIT_TIMEOUT` was reported as an error. This leads to a different exception being thrown, compared to before when `GetQueuedCompletionStatus` was used.
- Fixed to use similar logic to the SDK's `NT_SUCCESS` macro, which treats the `WAIT_TIMEOUT` value as a success, which is similar to what `GetQueuedCompletionStatus` does
- There are already tests that verify this behavior in `System.IO.Ports` tests, though [they are currently disabled](https://github.com/dotnet/runtime/blob/b39d6a6eb44860746e91e5ce4f585beff33d1f63/src/libraries/System.IO.Ports/tests/Support/TCSupport.cs#L108-L118) due to instabilities. I have verified locally that the relevant failures are fixed and that there are no new failures in those tests.

Relevant to #80079
  • Loading branch information
kouvel authored Feb 9, 2023
1 parent 2964613 commit 75979eb
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ internal static partial class Interop
{
internal static class StatusOptions
{
// See the NT_SUCCESS macro in the Windows SDK, and
// https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values
internal static bool NT_SUCCESS(uint ntStatus) => (int)ntStatus >= 0;

// Error codes from ntstatus.h
internal const uint STATUS_SUCCESS = 0x00000000;
internal const uint STATUS_SOME_NOT_MAPPED = 0x00000107;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ public static void Invoke(Event e)
// The NtStatus code for the operation is in the InternalLow field
uint ntStatus = (uint)(nint)e.nativeOverlapped->InternalLow;
uint errorCode = Interop.Errors.ERROR_SUCCESS;
if (ntStatus != Interop.StatusOptions.STATUS_SUCCESS)
if (!Interop.StatusOptions.NT_SUCCESS(ntStatus))
{
errorCode = Interop.NtDll.RtlNtStatusToDosError((int)ntStatus);
}
Expand Down

0 comments on commit 75979eb

Please sign in to comment.