-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Breaking change with timeout reading serial port in .NET 7 (Possible Overlapped I/O change) #80079
Comments
See workaround for this issue in #78319 (note it was closed as dup since this one has more details) |
Given System.IO.Ports is a nuget package and there is a workaround I suggest we just do fix in vNext. |
I also have this issue with .NET 7 serial port code (it used to work in .NET 4.8). |
What is the ETA for the fix? Is it just going to be a new https://nuget.info/packages/System.IO.Ports/7.0.0 or a .NET 7 fix? |
@hugo-lyppens I can't promise anything specific to a timeline. I couldn't pinpoint any specific change which could have regressed this so I've done some sanity testing and here are my findings:
Given above this doesn't look like regression was in System.IO.Ports and was likely somewhere on System.IO layer. @dotnet/area-system-io will need to take a look and from there we can decide on the next steps |
Tagging subscribers to this area: @dotnet/area-system-io Issue DetailsDescriptionIn .NET 6 and earlier, when Reproduction StepsUse the following code (substitute your own valid serial port values)
Expected behaviorOutput of Actual behaviorOutput of Regression?Yes. Worked for .NET 6 and 5. You can easily test this but switching target framework. If you switch to .NET 6 you get the Known WorkaroundsCode catching the Configuration.net 7.0.101 Windows 11, Target X64 or x86 has the problem. Ubuntu WSL2 with 7.0.101 does not have the problem. Other informationThis seems to be caused by changed in overlapped IO introduced in .net7 The difference can be observed here: runtime/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs Line 1505 in d099f07
On .net6, the errorCode is 0, on .net7 it's 1460 The call stack invoking this function is very different on .net 6 and 7. On .net7, runtime/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.IO.Windows.cs Line 262 in d099f07
On .net6, it's getting called from
|
This is likely caused by a switch to portable thread pool. cc @kouvel |
Tagging subscribers to this area: @mangod9 Issue DetailsDescriptionIn .NET 6 and earlier, when Reproduction StepsUse the following code (substitute your own valid serial port values)
Expected behaviorOutput of Actual behaviorOutput of Regression?Yes. Worked for .NET 6 and 5. You can easily test this but switching target framework. If you switch to .NET 6 you get the Known WorkaroundsCode catching the Configuration.net 7.0.101 Windows 11, Target X64 or x86 has the problem. Ubuntu WSL2 with 7.0.101 does not have the problem. Other informationThis seems to be caused by changed in overlapped IO introduced in .net7 The difference can be observed here: runtime/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs Line 1505 in d099f07
On .net6, the errorCode is 0, on .net7 it's 1460 The call stack invoking this function is very different on .net 6 and 7. On .net7, runtime/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.IO.Windows.cs Line 262 in d099f07
On .net6, it's getting called from
|
- 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. Fixes dotnet#80079
…ort`) - Port of dotnet#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 dotnet#80079
The A workaround is to set the environment variable I have put up PRs for fixes in #81744 (main) and #81745 (7.0). |
It's a .NET 7 fix. If the 7.0 PR is approved it'll be marked with a milestone indicating the runtime version that would include the fix. |
…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
…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. Fixes #80079
Description
In .NET 6 and earlier, when
System.IO.Ports.SerialPort.Read
times out, it will throw aTimeoutException
. In .NET 7, it will throw anIOException
with an HResult of 0x800705B4 (1460: ERROR_TIMEOUT)Reproduction Steps
Use the following code (substitute your own valid serial port values)
System.IO.Ports
version 7.0.0 (OK with eariler versions too)net7.0
to see it fail, ornet6.0
to see it work.Expected behavior
Output of
.NET <=6 Timed out
Actual behavior
Output of
.NET 7: IO 1460 HR:0x800705B4
Regression?
Yes. Worked for .NET 6 and 5.
You can easily test this but switching target framework. If you switch to .NET 6 you get the
TimeoutException
, if you switch to .NET 7 you get theIOException
Known Workarounds
Code catching the
TimeoutException
would have to catch theIOException
check the HResult and handle it the same way.Configuration
.net 7.0.101 Windows 11, Target X64 or x86 has the problem.
Debug or release doesn't seem to matter.
Ubuntu WSL2 with 7.0.101 does not have the problem.
Other information
This seems to be caused by changed in overlapped IO introduced in .net7
The difference can be observed here:
runtime/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs
Line 1505 in d099f07
On .net6, the errorCode is 0, on .net7 it's 1460
The call stack invoking this function is very different on .net 6 and 7.
On .net7,
AsyncFSCallback
is getttiong called fromPortableThreadPool
and the error is set here:runtime/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.IO.Windows.cs
Line 262 in d099f07
On .net6, it's getting called from
_IOCompletionCallback.PerformIOCompletionCallback
The stack stops there, and I didn't dig any deeper to see where it's getting its parameters from.The text was updated successfully, but these errors were encountered: