-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Basic implementation for testing of COM activation of a .NET class #19760
Basic implementation for testing of COM activation of a .NET class #19760
Conversation
b8c50af
to
b27c4db
Compare
@@ -0,0 +1,275 @@ | |||
// Licensed to the .NET Foundation under one or more agreements. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @morganbr This is the library I am adding to enable hosting when starting in a native entry point. I have also written a mechanism that allows native EXEs to be launched as the test entry point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this library a shipping code, or just a test-only code (like corerun.exe)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is equivalent to corerun.exe
- my understanding is that all the projects under the hosts/
are for testing and all real hosts should be contained in the core-setup repo. Am I missing the point of this directory?
Will be filling out the Native client to match the support already present in the .NET client. Once this is complete, the basics for managed activation will be defined. Additional investigations will can then be used to address the gaps in the proposal dotnet/core-setup#4476. |
@dotnet-bot test all please |
Console.WriteLine($"Searching for exe to launch in {workingDir}..."); | ||
|
||
string startExe = string.Empty; | ||
foreach (string exeMaybe in Directory.EnumerateFiles(workingDir, "*.exe")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to filter out the launch module itself.
assemPathLocal = Path.ChangeExtension(assemPath, ".dll"); | ||
} | ||
|
||
assem = Assembly.LoadFrom(assemPathLocal); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Loading a bunch of assemblies using LoadFrom is asking for problems. The dependencies of these assemblies may not be resolved correctly, and the app may not expect all of them to be loaded.
And then loading all types in these assemblies using GetTypes is performance trap.
Is this temporary hack?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. This is purely for satisfying test bring up. Once the API surface area is signed off, we need to do a lot more here. Figure out ALC and such along with probably trying to parse metadata instead of loading the assembly itself. Perhaps using Assembly.ReflectionOnlyLoadFrom()
in the long run?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will be looking to @vitek-karas to keep my honest here :-) Is the Assembly.ReflectionOnlyLoadFrom()
the right API to interrogate the types in an assembly without perturbing the running CLR instance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReflectionOnlyLoadFrom is not supported in .NET Core.
Is there no way to avoid the linear search to find the right type? I think we should have the type name in some manifest to avoid the linear search.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there no way to avoid the linear search to find the right type? I think we should have the type name in some manifest to avoid the linear search.
There are options I still need to explore, but in this case that is really secondary. The real issue is finding which assembly in the activation context is the assembly with the type in question. In the example there is one assembly, but conceivably there could be N assemblies and each need to be queried to determine the one that provides the type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the better question here is what is the appropriate way to read an assemblies metadata without loading the assembly into the current CLR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Unmanaged: IMDInternalImport interface
- Managed: System.Reflection.Metadata https://github.com/dotnet/corefx/tree/master/src/System.Reflection.Metadata
cc @vitek-karas This PR represents the broad strokes of the design described in dotnet/core-setup#4476 |
{ | ||
private readonly Guid classId; | ||
private readonly Type classType; | ||
private readonly Assembly classAssembly; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need to store the assembly here - if nothing else it can be asked on the type, but the class should not need to know the assembly to do anything anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@dotnet-bot test all please |
@dotnet-bot help |
Welcome to the dotnet/coreclr Repository The following is a list of valid commands on this PR. To invoke a command, comment the indicated phrase on the PR The following commands are valid for all PRs and repositories. Click to expand
The following jobs are launched by default for each PR against dotnet/coreclr:master. Click to expand
The following optional jobs are available in PRs against dotnet/coreclr:master. Click to expand
Have a nice day! |
@dotnet-bot test ci please |
Welcome to the dotnet/coreclr Perf help The following is a list of valid commands on this PR. To invoke a command, comment the indicated phrase on the PR The following commands are valid for all PRs and repositories. Click to expand
The following jobs are launched by default for each PR against dotnet/coreclr:master. Click to expand
The following optional jobs are available in PRs against dotnet/coreclr:master. Click to expand
Have a nice day! |
@dotnet-bot test this please |
@jkotas @luqunl @vitek-karas @jeffschwMSFT Any additional concerns/comments on this? |
std::wstring pathLocal; | ||
if (path == nullptr) | ||
{ | ||
pathLocal = GetEnvVar(W("CORE_ROOT")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this temporary? If you intend for it to be permanent, we should talk about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what we want for testing because that is where coreclr is consumed during testing. What are you thinking it should be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is test code only, no concerns.
|
||
pathLocal.append(W("\\coreclr.dll")); | ||
|
||
AutoModule hmod = ::LoadLibraryExW(pathLocal.c_str() , nullptr, LOAD_WITH_ALTERED_SEARCH_PATH); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want the full behavior of altered_search_path, we just want to search the directory we asked for. I think that would be LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
. Note that using that flag requires first probing for the AddDllDirectory API similar to:
Lines 6524 to 6532 in 246ae78
// Check if the OS supports the new secure LoadLibraryEx flags introduced in KB2533623 | |
HMODULE hMod = CLRGetModuleHandle(WINDOWS_KERNEL32_DLLNAME_W); | |
_ASSERTE(hMod != NULL); | |
if (GetProcAddress(hMod, "AddDllDirectory") != NULL) | |
{ | |
// The AddDllDirectory export was added in KB2533623 together with the new flag support | |
s_fSecureLoadLibrarySupported = true; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can change to that, but I want to be clear here this shim is only for the testing environment. There are way bigger issues in here if this was going to be used as the actual product shim.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is just testing, I'm not concerned. You might still want LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
to avoid accidentally picking up stray CoreCLRs from your path or working directory though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is a good suggestion and i will update it. Thanks.
std::wstring w_dirLocal; | ||
if (dir == nullptr) | ||
{ | ||
w_dirLocal = GetEnvVar(W("CORE_ROOT")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question about this variable.
The test hosts are fine (test code for now, so no trouble). But the managed part in System.Private.* should be product quality. Currently there are several todos there:
I think we should have at least understanding what are the plans on these. |
This is going to be done through metadata, but at the moment isn't needed for testing. There are several outstanding questions here, but the API contract is sound and is basically the point of the PR at present. A side note here, is that we have a basic trade-off here. Do a linear search, create yet another parser in native code (i.e. XML), or move activation into an external NuGet library. All are valid options, but have significantly different costs. At present the linear search is enough for testing and isn't exposed and can be improved upon behind the present interface.
I have stubs for logging and will fill them in as soon as I hear of an option. Rumor has it, you are going to be providing a design doc/proposal soon? 😄
I will add a stub for this. My plan is to handle all registry access in native instead of relying on the managed API. The stub I will add will be a QCall into coreclr.dll and it will return the registry details. The intent of doing the work in native is that it will keep registry access in a location that is quick to implement and avoid creating additional managed library dependencies. |
The managed registry APIs are available in CoreLib. (I do not have a problem with doing this via QCall ... but just want to make sure you will do it for the right reason.) |
private static bool IsLoggingEnabled() | ||
{ | ||
#if DEBUG | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not be doing this logging by default to debug output in debug builds. It is annoying to keep looking at somebody else's logs in debug output that you do not care about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I think the enable/disable logic is something I need guidance on, but is really apart of the general logging/diagnostic approach. @vitek-karas any thoughts on how we would like to enable disable this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's only for development of this thing for now, then a compile time define would be enough.
If we think we need this a bit broadly... the answer depends on the discussion about logging below. If we're going to use the same infra as binder, then you'll get it for free.
If not, then you could use EventSource directly.
@jkotas w00t! Thanks for letting me know. I was just trying to avoid bringing in more managed dependencies, but if this already exists, I will investigate this approach. Another factor in my natice decision was to consolidate registry access logic. If I can remove the existing native registry logic, I will do it all in managed, otherwise back to QCall 😄 |
@AaronRobinsonMSFT RE logging |
@dotnet-bot test Ubuntu x64 Checked Innerloop Build and Test |
@dotnet-bot test Ubuntu x64 Checked CoreFX Tests |
…launch a local EXE. This is useful when the test scenario's entry point is native.
Add property to exclude default assertion file Display exe ExeLaunchProgram class is going to launch
Consume the ExeLauncherProgram.cs file as a wrapper for the native test
…there is no way to determine that is the platform.
531d058
to
b607d44
Compare
This represents a partial implementation for dotnet/core-setup#4476
It current contains the following:
CoreShim
library is analogous to theCoreRun
exe and only for testingcc @jkotas @jeffschwMSFT @luqunl