-
Notifications
You must be signed in to change notification settings - Fork 94
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
Friendly overloads for NativeOverlapped not working #1066
Comments
Is this an issue with interpreting annotations? I understand interpreting [in] as won't be modified, vs. [in, out] where it could be. But doesn't LPOVERLAPPED mean that it's a pointer to an OVERLAPPED, and while the pointer isn't going to be modified, the OVERLAPPED could be? Somewhere around here? CsWin32/src/Microsoft.Windows.CsWin32/Generator.FriendlyOverloads.cs Lines 341 to 345 in baddb6d
|
@Tratcher While I look into this, it sounds like just calling the |
The extern overload doesn't do the SafeHandle management. I'm not currently blocked, I have the old pinvokes, I'd just like to get rid of them. |
True. You could do that yourself though by writing your own overload. I'm trying to get my head around the actual bug here. The annotation on the parameter suggests that the native code will not write at the memory pointed to by I see in the docs that folks shouldn't use the same struct across multiple calls concurrently. Since it's actually a pointer being passed in, I suppose that means that you're not supposed to pass in the same pointer. And if that matters, I'll further suppose that the method retains that pointer after the call is over. This is a deviation from the norm for win32. The norm led CsWin32 to only pin the struct in memory during the call. But if this is an API that needs to pin it beyond that, we need CsWin32 to never use Does that sound right? |
I wouldn't classify this as anything out of the norm. See also documented asynchronous I/O procedure. |
I think what happens is that the overlapped structure is updated during the initial native call. It's an IN because the pointer isn't modified, but the memory it points to could be. And yes, .NET does manager the lifetime and pinning of this memory. |
The pointer is passed by value (as all args are). The [in] marker can only meaningfully describe what is done to pointed memory. If it's marked as [in], yet the memory pointed to is mutated, then that's inconsistent and a bug in the declaration.
I don't think it does. The extern overload takes a pointer, which means the memory management is in the hands of the caller (not .NET, as pointers are unmanaged). The 'friendly' overload similarly makes it own pointer, which is to memory that it pins directly. But it unpins it once the call has completed. After that, the memory (which was on the stack because the struct is copied for the method call) is no longer safe to access. Thank you for your link, @riverar. In that doc, I found this:
That seems to confirm my hypothesis. |
Right. The Win32 Overlapped semantics are pretty clear and in/out semantics are how they work generally.
Yep. I would argue this is a bug in the declaration. I think CsWin32 is doing the right thing here because it was lied to, not because there is a mistake in the generator. |
So you're saying that the OVERLAPPED struct is modified by win32? I couldn't find anything that indicated that in the documentation that @riverar linked to. But maybe I missed it. As for CsWin32 doing the right thing, I'm not sure I agree. My interpretation of the doc is that the |
@AArnott Yep, the |
Right. The |
The |
Actual behavior
Generated APIs that take [In] NativeOverlapped object don't work, causing null refs in the callbacks when trying to retrieve the original state.
Expected behavior
We've (@AaronRobinsonMSFT) found that NativeOverlapped parameters need to be passed by ref (NativeOverlapped*) in both generated signatures so that the native call can correctly update the value.
Repro steps
NativeMethods.txt
content:Generated API:
When I copy and modify the generated code as follows it works:
I found #545 which first introduced NativeOverlapped support for ReadFile and I see that NativeOverlapped* is generated correctly there.
Use generated PInvokes and exchange types dotnet/aspnetcore#50685
Context
LangVersion
previewThe text was updated successfully, but these errors were encountered: