-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
How to pass APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS using hostfxr #39587
Comments
Tagging subscribers to this area: @vitek-karas, @swaroop-sridhar, @agocke |
This option is left-over from Silverlight. It worked ok for Silverlight sandboxed applications that were severely limited in what they can do. For .NET Core, there is number of ways managed exceptions can go unhandled even when this is set. I am not sure whether it makes sense to try to make it more first class in its current form. It is a poorly defined feature. Related discussion: #11546 |
|
This may not be supported, but if you call |
@rseanhall I don't really want to initialize it twice. It may create some unwanted effects. |
I'm just trying to point out a potential workaround in versions of the runtime where this isn't implemented. It's not possible to initialize the runtime multiple times. The |
I appreciate your help and got your idea. I just feel that workaround will bite me later. But looks like there is no other choice. |
Unhandled exceptions in embedded CoreCLR is a serious problem. In our case, the runtime is embedded into a game engine. To achieve a similar behavior like in Unity with Mono where unhandled exceptions are implicitly redirected to the console window and log files of the engine, we wrap the entire functionality with a single function like this, which invokes managed function pointers from unmanaged code here. As you can see, that means a very limited and predefined set of function signatures that can be used for execution, and it also involves performance cost. This way we prevent termination of the process, and handle redirection of unhandled exceptions to log files, the console window, and on-screen messages of the engine. It would be great if we get a hostfxr functionality that allows us to redirect exceptions to a custom function without handling them explicitly with try-catch blocks to prevent termination of the process. |
@nxrighthere : The important distinction between Mono's native APIs and the hostfxr based native hosting of CoreCLR is that Mono implements a full set of embedding APIs - so it can handle exceptions, GC interactions, reflection, managed object creation and so on, all from native code. That was not the aspiration of the hostfxr based native hosting APIs for CoreCLR. The design for hostfxr native hosting was to allow execution of a simple managed entry point from various scenarios. It is fully expected, that if a more complex communication is to be created between the native and managed side, there would be custom code to handle that. That includes exception handling. We also discussed what it would mean to implement full embedding APIs for CoreCLR, but other than the obvious (lot of work) it would also require non-trivial amount of design - mono embedding API has known issues/limitations which we would like to avoid, CoreCLR has slightly different behavior in certain cases and so on. Hopefully we'll get to it at some later date. The question in this issue is about handling exception on other threads when using native hosting APIs - which doesn't seem to be the issue you're trying to solve. |
Our only problem as stated in this issue:
Personally, we don't really need embedding API similar to Mono, but we need a way to at least stop the termination of the process because in the development stage where a product is not ready for consumption by the end-user it makes no sense. If a game is in development under the full control of IDE and a debugger before we ship it, what's the point to terminate the entire environment once an unhandled exception occurs? It makes sense to terminate the process when a game/application shipped to a customer, but before that, it doesn't carry any benefits. |
Please, can we reach a consensus regarding hostfxr API that will allow preventing termination of the process? We are considering forking CoreCLR to modify that part for our needs to stop crashing the editor of the engine as long as the application is in development. This issue is a ship stopper for us, and we can't implement new features for our customers because of that. |
Same here, we cannot switch to hoxtfxr and have to use using-mscoreeh method to host runtime. I'm curing are they planning to use .NET 5 in SQL Server? How SQL Server team will solve it? |
There are no plans to for SQL CLR based on .NET 5. |
@nxrighthere @cheverdyukv Could you please share API proposal(s) that you would like to see added to address your scenarios? The API signature (either managed or unmanaged), how the API would be used and details about the guarantees that the API would provide. Let's treat this as a new API proposal and pretend that |
A perfect solution in our case would be API similar to |
It can be done on threads started by .NET runtime. What should it do on foreign threads? |
I believe that foreign threads belongs to host and host should deal with them. Do runtime terminates process in this case? |
My proposal would be API that allows spawning threads from .NET runtime instead of using native platform-specific/language-specific API so the application that embedding hostfxr can use it instead. |
They belong to whoever created them. For example, the thread may be created by the OS or a library.
On Windows, the runtime lets the exception to propagate using SEH. It typically results into exception being unhandled. It is a bad practices for libraries to handle exceptions that they do not understand. |
It would not solve the problem with the foreign threads. |
@jkotas Could you please elaborate on "On Windows, the runtime lets the exception to propagate using SEH"? If some host thread will call runtime and there is unhanded exception I think thread function should deal with that. If it is say OS thread pool thread and there is exception, allow thread pool deal with that. Basically exception would be propagated to caller. |
Host process should be in control on any runtime decision about whether terminate process or not. It is really like how SQL Server hosts .NET runtime. Runtime in this case is just guest in somebody’s house and it should not enforce its own rules. I can accept that certain exceptions like memory corruption, stack overflow or out of memory, will lead to process termination. Handling these cases is really hard. But all other type of unhandled exceptions should go via some global handler. Handler should accept exception object and returns if it is ok to terminate application. I believe that I think it should be in managed code, because there is no API to process exception. Depending on result, exception can be suppressed, suppressed and |
@jkotas If I understand you correctly, you would like to handle edge cases where the code in the host application is not aware of .NET runtime but still interoperate with managed code? |
We are talking about host, not library. |
I would stick with the current proposal. Introducing a setter for |
@janvorli @vitek-karas Could you please chime in your thoughts about the managed API shape? Once we get a local agreement, I am going to create API proposal issue to submit for API review approval. |
Personally I think |
The proposal sounds good. Do we know how mono/Xamarin behave in this area today? That is - is the |
The proposal makes sense to me too. |
I think so. @lambdageek Do you have any concerns about 1. from #39587 (comment) from the Mono side? |
Right now Mono always passes If I understand the proposal (1), we would pass I don't think this will be a problem for Mono. From an embedding point of view, I think it would be interesting to think about foreign threads that are allowed to set |
API proposal issue: #42275 |
Is there any progress being made? I'm currently working on a Mod Manager for FF7 on PC ( https://github.com/tsunamods-codes/7th-Heaven ) and I've been impacted exactly by this. By hooking two APIs ( CloseHandle and DuplicateHandle ) using the Hostxfr, which do throw unhandled exceptions if the handle is invalid, makes the game crash. Having the possibility to ignore unhandled exceptions or handle them instead of force closing the process would be HIGHLY appreciated. Thank you in advance. |
You can use GetCLRRuntimeHost to initialize runtime second time and disable unhanded exceptions. I didn't full battle test it, but our huge app starts fine with it. I also test it with unhanded exception and it suppresses them. It just must be at appropriate time. |
@vladimir-cheverdyuk-altium I'd be very interested to test this. Do you have a sample code I can use as a basis? Thanks! |
I have it but it in Delphi (Pascal like language). If you want I can paste a few functions here. |
Yep, fine by me. I can relate, thanks :) |
|
Amazing! Thanks a lot @vladimir-cheverdyuk-altium very interesting approach, I'll try to translate this into C++ native code and I'll post here the results ASAP I'll be able to test this. Cheers! |
Great! |
Just in case this code is assume that framework will be packaged with application and there will be .runtimeconfig.json file that application used for own needs in different than intended way. I just pasted that code to demonstrate where you need to call DisableUnhandledExceptions. |
Yup, crystal clear how's the approach, I never thought about "abusing it" this way, pretty smart move. It might solve also my own issues. Thanks again, appreciated! |
Allright for anyone interested I translated this into C++, unfortunately doesn't fix my issue but the code works as intended: #include <stdio.h>
#include "mscoree.h" // https://github.com/dotnet/coreclr/blob/master/src/pal/prebuilt/inc/mscoree.h
hostfxr_handle context = nullptr; // here lives the hostfxr context from hostfxr_initialize_for_runtime_config()
static const wchar_t* coreCLRInstallDirectory = L"%programfiles%\\dotnet\\shared\\Microsoft.NETCore.App\\7.0.0";
static const wchar_t* coreCLRDll = L"coreclr.dll";
// -------------------------------
// Check for CoreCLR.dll in a given path and load it, if possible
HMODULE LoadCoreCLR(const wchar_t* directoryPath)
{
wchar_t coreDllPath[MAX_PATH];
wcscpy_s(coreDllPath, MAX_PATH, directoryPath);
wcscat_s(coreDllPath, MAX_PATH, L"\\");
wcscat_s(coreDllPath, MAX_PATH, coreCLRDll);
return LoadLibraryExW(coreDllPath, NULL, 0);
}
void DisableUnhandledExceptions()
{
wchar_t coreRoot[MAX_PATH];
::ExpandEnvironmentStringsW(coreCLRInstallDirectory, coreRoot, MAX_PATH);
HMODULE coreCLRModule = LoadCoreCLR(coreRoot);
ICLRRuntimeHost2* runtimeHost;
FnGetCLRRuntimeHost pfnGetCLRRuntimeHost =
(FnGetCLRRuntimeHost)::GetProcAddress(coreCLRModule, "GetCLRRuntimeHost");
// Get the hosting interface
HRESULT hr = pfnGetCLRRuntimeHost(IID_ICLRRuntimeHost2, (IUnknown**)&runtimeHost);
runtimeHost->Start();
size_t num_props = 0;
DWORD domainId;
hostfxr_get_runtime_properties(context, &num_props, nullptr, nullptr);
const char_t** fxr_keys = new const char_t * [num_props];
const char_t** fxr_values = new const char_t * [num_props];
hostfxr_get_runtime_properties(context, &num_props, fxr_keys, fxr_values);
// Create the AppDomain
hr = runtimeHost->CreateAppDomainWithManager(
L"Default Domain",
APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS ||
APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP ||
APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT ||
APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS,
NULL,
NULL,
num_props,
fxr_keys,
fxr_values,
&domainId
);
}
// Just call DisableUnhandledExceptions() after hostfxr_close(); Main differences from the above version:
Feel free to tweak at your own heart and desire. Thanks again @vladimir-cheverdyuk-altium for the snippet on your side! |
Does it suppress unhanded exceptions? |
Please check #101560 and let us know if it addresses your scenario. |
Hi @jkotas. It looks like what we want to. Thank you! |
I'm going to close this against #101560, as that seems to address the requested scenarios here. |
I was using https://docs.microsoft.com/en-us/dotnet/core/tutorials/netcore-hosting#create-a-host-using-mscoreeh to host .NET runtime. But after discussion in #39167 I was told to use hostfxr to host .NET runtime.
But as far as I can see there is no way to pass APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS and our application needs for 2 reasons:
This is last issue that prevents us to use hostfxr
The text was updated successfully, but these errors were encountered: