-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
[NativeAOT Library] Exceptions thrown from [UnmanagedFunctionPointer]
delegate can't be caught in [UnmanagedCallersOnly]
method
#97952
Comments
[UnmanagedFunctionPointer]
delegate can't be caught in [UnmanagedCallersOnly]
method[UnmanagedFunctionPointer]
delegate can't be caught in [UnmanagedCallersOnly]
method
Does it work if you use |
Worth noting that passing exceptions through native code is Windows only (and even there can break a lot of native code that's not prepared for it) and guaranteed to fail-fast on other platforms. |
This suggestion does not apply: |
Good point: it's not something I tried recently (I am curious and I will test it later in linux) but yes, if the runtime can't unwind the native stack in other platforms as it's possible in Windows, then fail-fast is the most safe behavior. Still I believe when everything gets NAOT compiled this possible limitation may not exist. It is worth noting that in the NAOT scenario I also tried compiling my C++ library |
Interop with unmanaged exception handling is supported only by regular CoreCLR and only on Windows. It is not supported by native AOT. The recommended portable solution is #35017 (comment) |
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas Issue DetailsDescriptionExceptions thrown from A sample showing the issue using the above strategy for error handling in native libraries (C++ in the sample) is attached. The solution is composed by the following projects:
Reproduction Steps
Expected behaviorI'm expecting exceptions thrown from Actual behaviorThe exceptions thrown from Regression?No response Known WorkaroundsThe only workaround I can imagine at the the moment is to not throw exceptions in ConfigurationNo response Other information.NET 8.0.101 (Visual Studio 2022 17.8.6) I'm interested in testing also the other NAOT supported platforms, such as linux and macos.
|
Can you provide more insights why this limitation should apply to this specific use case of NativeAOT, as in my sample? In the boundary of the Native AOT generated shared library, everything gets natively compiled and there's should be only one (I guess) native stack. The exception thrown in the
So, why the Native AOT code should fast-fail? |
The |
@MichalStrehovsky So if I understood correctly, even in the case of Native AOT, throwing a "managed" natively compiled exception in the callback would not be able to propagate and unwind the stack in the external C++ code as in my sample, and safely be caught in the
@jkotas I had a look and I suggested an API to avoid the boilerplate code of checking and throwing exception on return from incompatible runtimes. Such API would apply to the use case of this issue as well. |
Nothing fundamental prevents native AOT from supporting exception handling interop on Windows in the same shape as regular CoreCLR. The downside is that it would make the exception handling subsystem in native AOT more complicated. The primary use case for exception handling interop on Windows is managed C++. Even though you can use it independently, it was specifically designed to enable managed C++. Managed C++ as a whole is not supported by native AOT. |
I think this issue can be closed since I got all the clarifications I asked for (throwing from |
Description
Exceptions thrown from
[UnmanagedFunctionPointer]
delegates are not caught bytry-catch
block in outer[UnmanagedCallersOnly]
NAOT compiled method. The issue looks critical to me as libraries may use this strategy for error handling (it's legal with CLR EDIT: only in Windows) and it's currently preventing me from using a large private library with native components in Native AOT scenarios.A sample showing the issue using the above strategy for error handling in native libraries (C++ in the sample) is attached. The solution is composed by the following projects:
CppNativeLibrary
that exportsFooNativeLibrary()
and provides customizable error handling through theSetErrorHandler()
export;NetNativeLibraryWrapper
C# library that wrapsCppNativeLibrary
through P/Invoke and defines a[UnmanagedFunctionPointer]
marked handler that installthe error handler for the C++ library. The handler acutally throws a
System.Exception
;NAOTLibrary
that exports a[UnmanagedCallersOnly]
markedFooNAOT()
method;TestExceptionThroughCallbackNAOT
C# CLR project that tests theFooNAOT()
method inNAOTLibrary
through P/Invoke.Reproduction Steps
TestExceptionThroughCallbackNAOT.sln
and compile the solution (re-build in case the executable complains with a "You must install or update .NET to run this application" error)TestExceptionThroughCallbackNAOT
project, the following unhandled exception pop-up should be shown:Expected behavior
I'm expecting exceptions thrown from
[UnmanagedFunctionPointer]
marked delegates in AOT compiled code to behave in a similar way they do in CLR, where the native stack gets unwind up to the[DllImport]
boundary and theSystem.Exception
regularly propagates in the managed stack. Because in this case everything gets natively compiled, the exception should just propagate to the the[UnmanagedCallersOnly]
marked method in theNAOTLibrary
project and be caught there.Actual behavior
The exceptions thrown from
[UnmanagedCallersOnly]
marked delegates in AOT compiled code are unhandled and the process quits with__fastfail()
, even if an outer try-catch exists.Regression?
No response
Known Workarounds
The only workaround I can imagine at the the moment is to not throw exceptions in
[UnmanagedFunctionPointer]
delegates and rely to classical C style return error codes.Configuration
No response
Other information
.NET 8.0.101 (Visual Studio 2022 17.8.6)
Windows 10 x64
I'm interested in testing also the other NAOT supported platforms, such as linux and macos.
The text was updated successfully, but these errors were encountered: