Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
On Unix, SafeFileHandle.IsAsync and FileStream.IsAsync now accurately reflect whether the underlying file descriptor has the O_NONBLOCK flag set. Previously, IsAsync unconditionally returned true for regular files opened with FileOptions.Asynchronous, even though regular file I/O on Unix is inherently synchronous at the kernel level.
Version introduced
.NET 11 Preview 3
Previous behavior
Previously, SafeFileHandle.IsAsync on Unix returned true for regular files opened with FileOptions.Asynchronous, even though no O_NONBLOCK flag was set on the file descriptor (regular file I/O on Unix is inherently synchronous). For file descriptors that were genuinely non-blocking, IsAsync incorrectly returned false on Unix.
using Microsoft.Win32.SafeHandles;
// On Unix, IsAsync was true for regular files opened with FileOptions.Asynchronous,
// even though the file descriptor had no O_NONBLOCK set.
using SafeFileHandle handle = File.OpenHandle("myfile.txt", options: FileOptions.Asynchronous);
Console.WriteLine(handle.IsAsync); // true (misleading; no O_NONBLOCK on regular file)
On non-Windows platforms, constructing a SendPacketsElement with a non-async FileStream threw an ArgumentException.
New behavior
Starting in .NET 11, SafeFileHandle.IsAsync on Unix returns true only when the underlying file descriptor has the O_NONBLOCK flag set, which is possible for pipes and sockets. For regular files, it returns false.
using Microsoft.Win32.SafeHandles;
// On Unix, IsAsync now reflects the actual
// non-blocking state of the file descriptor.
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 opened with FileOptions.Asynchronous, IsAsync correctly returns false on Unix because regular file I/O is inherently synchronous at the kernel level.
Additionally, on non-Windows platforms, constructing a SendPacketsElement with a FileStream no longer throws ArgumentException, regardless of whether the stream is async.
Type of breaking change
This change is a behavioral change.
Reason for change
The previous behavior was incorrect and misleading. SafeFileHandle.IsAsync reported false for file descriptors (such as pipes or sockets) that genuinely had O_NONBLOCK set. This caused APIs and user code that relied on this property to make incorrect decisions. Accurate IsAsync reporting was also a prerequisite for the new SafeFileHandle.CreateAnonymousPipe API to correctly expose per-end async semantics on Unix. For more information, see 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 alwaystrueon Unix for files opened withFileOptions.Asynchronous, update it to account for the fact that regular file handles now returnfalse.If you wrap a non-blocking
SafeFileHandlein aFileStream(for example, one created viaSafeFileHandle.CreateAnonymousPipewithasyncRead: trueorasyncWrite: true),FileStream.IsAsyncmight now returntruewhere it previously returnedfalse. Adjust downstream code accordingly.If you construct
SendPacketsElementwith aFileStreamon a non-Windows platform and previously expected anArgumentExceptionto be thrown for non-async streams, note that the exception is no longer thrown. Guard any such expectation withOperatingSystem.IsWindows().