-
Notifications
You must be signed in to change notification settings - Fork 6.1k
[Breaking change]: SafeFileHandle.IsAsync now accurately reflects non-blocking state on Unix #52886
Description
Description
In .NET 11, SafeFileHandle.IsAsync on Unix no longer unconditionally returns true for regular files opened with FileOptions.Asynchronous. It now accurately reflects whether the underlying file descriptor is in non-blocking mode (O_NONBLOCK is set), which is possible only for pipes and sockets. The same applies to FileStream.IsAsync.
Related PR: dotnet/runtime#125220
Version
.NET 11 Preview 3
Previous behavior
SafeFileHandle.IsAsync always returned true on Unix for regular files opened with FileOptions.Asynchronous, even when the underlying file descriptor had no O_NONBLOCK set (non-blocking/async mode).
// On Unix, IsAsync was true for regular files opened with FileOptions.Asynchronous, regardless of the actual fd state
using SafeFileHandle handle = File.OpenHandle("myfile.txt", options: FileOptions.Asynchronous);
Console.WriteLine(handle.IsAsync);New behavior
SafeFileHandle.IsAsync on Unix now returns true when the underlying file descriptor is in non-blocking mode (O_NONBLOCK is set), and false otherwise.
// On Unix, IsAsync now reflects the actual non-blocking state of the fd
SafeFileHandle.CreateAnonymousPipe(
out SafeFileHandle readHandle,
out SafeFileHandle writeHandle,
asyncRead: true,
asyncWrite: false);
Console.WriteLine(readHandle.IsAsync); // true (O_NONBLOCK set on read end)
Console.WriteLine(writeHandle.IsAsync); // false (blocking write end)For regular files on Unix opened with FileOptions.Asynchronous, IsAsync correctly returns false because regular file I/O on Unix is inherently synchronous at the kernel level.
Type of breaking change
- Behavioral change: Existing binaries might behave differently at run time.
Reason for change
The previous behavior was incorrect and misleading. SafeFileHandle.IsAsync reported false on Unix even for handles that were genuinely non-blocking, causing APIs and user code that relied on this property to make incorrect decisions. Accurate IsAsync reporting was a prerequisite for the new SafeFileHandle.CreateAnonymousPipe API to correctly expose per-end async semantics on Unix (also introduced in dotnet/runtime#125220).
Recommended action
Review any code that checks SafeFileHandle.IsAsync or FileStream.IsAsync on Unix and takes action based on the result:
-
If your code assumed
IsAsyncwas alwaysfalseon Unix, that assumption no longer holds for non-blocking file descriptors. Update any logic that unconditionally expectsIsAsync == falseon non-Windows. -
If you wrap a non-blocking
SafeFileHandlein aFileStream(for example, one created via the newSafeFileHandle.CreateAnonymousPipewithasyncRead: trueorasyncWrite: true),FileStream.IsAsyncmay now returntruewhere it previously returnedfalse. Adjust downstream code accordingly. -
If you construct
SendPacketsElementwith aFileStreamon a non-Windows platform and previously expectedArgumentExceptionto be thrown for non-async streams, note that this exception is no longer thrown on non-Windows. Guard any such expectation withOperatingSystem.IsWindows().
Feature area
Core .NET libraries
Affected APIs
Microsoft.Win32.SafeHandles.SafeFileHandle.IsAsyncSystem.IO.FileStream.IsAsyncSystem.Net.Sockets.SendPacketsElement.SendPacketsElement(System.IO.FileStream, System.Int64, System.Int32)(behavioral change on non-Windows)System.Net.Sockets.SendPacketsElement.SendPacketsElement(System.IO.FileStream, System.Int64, System.Int32, System.Boolean)(behavioral change on non-Windows)
Metadata
Metadata
Labels
Type
Fields
Give feedbackProjects
Status