-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Binding duplicated handle to ThreadPool fails? #28585
Comments
@poizan42 @JeremyKuhne although I was unable to find any statement in Win32 API documentation, my understanding is that it's not possible to bind a duplicate handle to a second IOCP port, therefore async operations on This is a known behavior for sockets (see #1760). |
Triage: It would be useful to try doing straight P/Invokes and confirm if handle duplication can be done as described. |
While working on #58381 I wanted to use Example: async Task<(SafeFileHandle readHandle, SafeFileHandle writeHandle)> GetNamedPipeHandlesAsync()
{
string name = FileSystemTest.GetNamedPipeServerStreamName();
var server = new NamedPipeServerStream(name, PipeDirection.In, -1, PipeTransmissionMode.Byte, PipeOptions);
var client = new NamedPipeClientStream(".", name, PipeDirection.Out, PipeOptions);
await Task.WhenAll(server.WaitForConnectionAsync(), client.ConnectAsync());
bool isAsync = (PipeOptions & PipeOptions.Asynchronous) != 0;
return (GetFileHandle(server, isAsync), GetFileHandle(client, isAsync));
}
private static SafeFileHandle GetFileHandle(PipeStream pipeStream, bool isAsync)
{
var serverHandle = new SafeFileHandle(pipeStream.SafePipeHandle.DangerousGetHandle(), ownsHandle: true);
pipeStream.SafePipeHandle.SetHandleAsInvalid();
return serverHandle;
} The problem is that when I use runtime/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs Lines 256 to 260 in e4b4666
and when I create a copy of it and try to re-use for async IO, I hit this condition: runtime/src/coreclr/System.Private.CoreLib/src/System/Threading/ClrThreadPoolBoundHandle.Windows.cs Lines 33 to 34 in 57bfe47
Minimal repro case using using Microsoft.Win32.SafeHandles;
using System;
using System.IO;
using System.Threading.Tasks;
namespace asyncHandles
{
class Program
{
static async Task Main(string[] args)
{
string filePath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
try
{
using FileStream fs1 = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write, 1, FileOptions.Asynchronous);
await fs1.WriteAsync(new byte[] { 1 }); // initializes SafeFileHandle.ThreadPoolBinding
SafeFileHandle duplicate = new(fs1.SafeFileHandle.DangerousGetHandle(), ownsHandle: false);
using FileStream fs2 = new FileStream(duplicate, FileAccess.Write, 1, isAsync: true);
await fs2.WriteAsync(new byte[] { 1 }); // throws
}
finally
{
if (File.Exists(filePath))
{
File.Delete(filePath);
}
}
}
}
}
I've used reflection as un ugly workaround hack: ThreadPoolBoundHandle threadPoolBinding = (ThreadPoolBoundHandle)typeof(PipeStream).GetField("_threadPoolBinding", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance).GetValue(pipeStream);
typeof(SafeFileHandle).GetProperty("ThreadPoolBinding", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance).GetSetMethod(true).Invoke(serverHandle, new object[] { threadPoolBinding }); We should take a look whether it's possible to just get |
I also just had this issue because I am trying to attach a serial port handle to the FileStream. At the very end this means abandoning |
From @poizan42 on June 13, 2018 4:6
When I run the following code I get a System.ArgumentException: ''handle' has already been bound to the thread pool, or was not opened for asynchronous I/O.'
This seems weird since it is a copy of the handle bound and it is definitely opened for async I/O. From a glance it looks like the error ultimately comes from CreateIoCompletionPort, but that is weird because the documentation implies that you can use DuplicateHandle to share a handle registered to an IO completion port:
Is the framework doing something funky here, or is the reality more complicated than the documentation for CreateIoCompletionPort would lead you to think?
This is tested on dotnet core 2.1.30 and Windows 10.0.17686.1003.
Copied from original issue: dotnet/coreclr#18450
The text was updated successfully, but these errors were encountered: