Skip to content
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

Remove the GetCLRRuntimeHost export from coreclr binary #52688

Open
AaronRobinsonMSFT opened this issue May 13, 2021 · 14 comments
Open

Remove the GetCLRRuntimeHost export from coreclr binary #52688

AaronRobinsonMSFT opened this issue May 13, 2021 · 14 comments
Milestone

Comments

@AaronRobinsonMSFT
Copy link
Member

The GetCLRRuntimeHost export on the coreclr binary is a way to get at the COM interface hosting API that is no longer supported in .NET 5+. We should get rid of this API and simplify the internal initialization logic by removing the COM API style. Since it is no longer supported and we have no test coverage assets it is sitting there waiting to get broken.

extern "C"
DLLEXPORT
HRESULT GetCLRRuntimeHost(REFIID riid, IUnknown **ppUnk)
{
WRAPPER_NO_CONTRACT;
return CorHost2::CreateObject(riid, (void**)ppUnk);
}

The new API is officially documented with guidance and a sample can be found here.

/cc @vitek-karas @elinor-fung

@ghost
Copy link

ghost commented May 13, 2021

Tagging subscribers to this area: @vitek-karas, @agocke, @VSadov
See info in area-owners.md if you want to be subscribed.

Issue Details

The GetCLRRuntimeHost export on the coreclr binary is a way to get at the COM interface hosting API that is no longer supported in .NET 5+. We should get rid of this API and simplify the internal initialization logic by removing the COM API style. Since it is no longer supported and we have no test coverage assets it is sitting there waiting to get broken.

extern "C"
DLLEXPORT
HRESULT GetCLRRuntimeHost(REFIID riid, IUnknown **ppUnk)
{
WRAPPER_NO_CONTRACT;
return CorHost2::CreateObject(riid, (void**)ppUnk);
}

The new API is officially documented with guidance and a sample can be found here.

/cc @vitek-karas @elinor-fung

Author: AaronRobinsonMSFT
Assignees: -
Labels:

area-Host

Milestone: -

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label May 13, 2021
@elinor-fung
Copy link
Member

elinor-fung commented May 13, 2021

If and when this happens, we should make sure it gets announced / tagged as a breaking change.

The startup flags should be achievable through runtime config properties via our recommended hosting APIs. I think the only AppDomain flags used in CreateAppDomainWithManager now are:

We should also have a better story for things like loading in the default ALC to replace ExecuteInDefaultAppDomain scenarios that actually need/expect the default ALC.

@vitek-karas vitek-karas added this to the 7.0.0 milestone Jul 9, 2021
@vitek-karas vitek-karas removed the untriaged New issue has not been triaged by the area owner label Jul 9, 2021
@agocke agocke added this to AppModel Jul 13, 2022
@agocke agocke modified the milestones: 7.0.0, 8.0.0 Jul 26, 2022
@batzen
Copy link
Contributor

batzen commented Jan 2, 2023

If it gets removed, what would be the suggested way to do things like ExecuteInDefaultAppDomain does?
Currently tools like Snoop use the export to get a handle to the runtime host and execute ExecuteInDefaultAppDomain afterwards.
Is there any alternative to call .NET code from C++ without using managed C++?

@AaronRobinsonMSFT
Copy link
Member Author

If it gets removed, what would be the suggested way to do things like ExecuteInDefaultAppDomain does?

@elinor-fung has been working on a solution to this problem. I believe it is a .NET 8 plan, but that will need to exist before we can remove this API.

Is there any alternative to call .NET code from C++ without using managed C++?

There are two approaches. The first is to NativeAOT your library and the second is to use the approach that is taken by DNNE.

@vitek-karas
Copy link
Member

There are two approaches. The first is to NativeAOT your library and the second is to use the approach that is taken by DNNE.

I don't think that applies in this case. If I understand it correctly Snoop wants to effectively call into already running managed code - I think it's something like a UI inspector tool which you "attach" to a process. So NativeAOT approach is not applicable because that would not attach to the existing runtime. And DNNE will run into the same limitation as mentioned above because it also relies on nethost/hostfxr.

@batzen
Copy link
Contributor

batzen commented Jan 3, 2023

Excatly. Snoop injects itself into a running WPF application to allow users to inspect/modify the UI etc., similar to the live visual tree in Visual Studio.
Because of that it has to execute it's code in the runtime started by the target process.

@AaronRobinsonMSFT
Copy link
Member Author

There are two approaches. The first is to NativeAOT your library and the second is to use the approach that is taken by DNNE.

I don't think that applies in this case.

I was narrowly answering the question of "Is there any alternative to call .NET code from C++ without using managed C++?". NativeAOT and DNNE are the specific answers to that. For the combination of calling from C++ and attaching to an existing runtime instance, I agree that is more complicated. @elinor-fung's proposal, if I recall, is around getting access to the Default ALC and injecting into that so that would be the API.

I was also under the impression that an already loaded hostfxr will know the current coreclr and can then "attach". If the desired runtime versions match, the DNNE approach would just need to call a different API for injection. I agree the NativeAOT approach is a non-starter for attaching and loading to an existing runtime instance.

@elinor-fung
Copy link
Member

getting access to the Default ALC and injecting into that

We currently have a way to get a function pointer to something already loaded into the default ALC, but no way to load an assembly in the default ALC. #77696 is the rough idea for adding a similar API that allows loading an assembly into the default ALC.

I was also under the impression that an already loaded hostfxr will know the current coreclr and can then "attach".

nethost looks for an already loaded hostfxr. Assuming the runtime was originally started using hostfxr (so 'normal' app run or a native host loading the runtime using hostfxr - as opposed to a native host directly loading coreclr itself), it will 'attach'.

@vitek-karas
Copy link
Member

The original ask is probably based on the discussion here: #80092
The nethost solution once we support loading assemblies into default ALC will work for non-single-file apps. It still doesn't solve the single-file problem because in that case there's no hostfxr module, the hostfxr functionality is part of the executable directly (and is somewhat different, so it's not even clear if it could be used by component loading even if it could be found).

@batzen
Copy link
Contributor

batzen commented Jan 4, 2023

Single-file wouldn't be a problem if the single-file host application would contain some exports from hostfxr, which shouldn't be a huge problem, or am i missing something?

That way one could either look for a loaded hostfxr or try ::GetProcAddress(::GetModuleHandle(nullptr), "exportName") if there is no hostfxr.

The reason why i am using GetCLRRuntimeHost is that it already allows loading assemblies into default ALC and the API is much simpler than using hostfxr.
At least if you don't have to start a runtime but depend on an already running runtime.
It's just a call to GetCLRRuntimeHost and then a call to ICLRRuntimeHost::ExecuteInDefaultAppDomain.

@vitek-karas
Copy link
Member

@batzen If the functionality exists in the single-file then I agree. But ideally the workflow using our hosting APIs would look the same (or very similar) for single-file and non-single-file.

There's the added issue that we compile a slightly different version of hostfxr code into single-file - it can make certain assumptions and make the code smaller/faster. With this we would have to guarantee that it also provides all of the necessary functionality for hosting APIs to work correctly. Definitely doable, but I don't know if it's the case today.

@batzen
Copy link
Contributor

batzen commented Jan 4, 2023

@vitek-karas I would go one step further and say the APIs must look the same. The hosting is already quite complex. Having to deal with different APIs would be very far from ideal.

To get back to my original question:
I hope that GetCLRRuntimeHost etc. won't get removed till there is a complete alternative that allows achieving the same (executing code in an already running runtime).

@vitek-karas
Copy link
Member

I would go one step further and say the APIs must look the same

I agree - the problem is that the existing APIs might not be good enough to support it (specifically the nethost which returns path to hosfxr, which doesn't make sense for single-file). So we may need to introduce a new API - which then should work for all cases.

@elinor-fung
Copy link
Member

elinor-fung commented Jan 4, 2023

Ah, thanks for the context - yeah, the existing APIs don't work with self-contained single-file and singlefilehost doesn't export any hosting APIs like hostfxr. #3773 tracks hosting components not working with that scenario. @vitek-karas also has a nice write-up at #40802 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

No branches or pull requests

5 participants