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

Allow interop resolvers to return self handle #78004

Merged
merged 5 commits into from
Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 37 additions & 25 deletions src/mono/mono/metadata/native-library.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,40 @@ netcore_probe_for_module_nofail (MonoImage *image, const char *file_name, int fl
return result;
}

static MonoDl*
netcore_lookup_self_native_handle (void)
{
ERROR_DECL (load_error);
if (!internal_module)
internal_module = mono_dl_open_self (load_error);

if (!internal_module)
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", mono_error_get_message_without_fields (load_error));

mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal.");
mono_error_cleanup (load_error);

return internal_module;
}

static MonoDl* native_handle_lookup_wrapper (gpointer handle)
{
MonoDl *result = NULL;

if (!internal_module)
netcore_lookup_self_native_handle ();

if (internal_module->handle == handle) {
result = internal_module;
} else {
native_library_lock ();
result = netcore_handle_lookup (handle);
native_library_unlock ();
}

return result;
}

static MonoDl *
netcore_resolve_with_dll_import_resolver (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, const char *scope, guint32 flags, MonoError *error)
{
Expand Down Expand Up @@ -631,9 +665,7 @@ netcore_resolve_with_dll_import_resolver (MonoAssemblyLoadContext *alc, MonoAsse
mono_runtime_invoke_checked (resolve, NULL, args, error);
goto_if_nok (error, leave);

native_library_lock ();
result = netcore_handle_lookup (lib);
native_library_unlock ();
result = native_handle_lookup_wrapper (lib);

leave:
HANDLE_FUNCTION_RETURN_VAL (result);
Expand Down Expand Up @@ -688,9 +720,7 @@ netcore_resolve_with_load (MonoAssemblyLoadContext *alc, const char *scope, Mono
mono_runtime_invoke_checked (resolve, NULL, args, error);
goto_if_nok (error, leave);

native_library_lock ();
result = netcore_handle_lookup (lib);
native_library_unlock ();
result = native_handle_lookup_wrapper (lib);

leave:
HANDLE_FUNCTION_RETURN_VAL (result);
Expand Down Expand Up @@ -755,9 +785,7 @@ netcore_resolve_with_resolving_event (MonoAssemblyLoadContext *alc, MonoAssembly
mono_runtime_invoke_checked (resolve, NULL, args, error);
goto_if_nok (error, leave);

native_library_lock ();
result = netcore_handle_lookup (lib);
native_library_unlock ();
result = native_handle_lookup_wrapper (lib);

leave:
HANDLE_FUNCTION_RETURN_VAL (result);
Expand Down Expand Up @@ -802,22 +830,6 @@ netcore_check_alc_cache (MonoAssemblyLoadContext *alc, const char *scope)
return result;
}

static MonoDl*
netcore_lookup_self_native_handle (void)
{
ERROR_DECL (load_error);
if (!internal_module)
internal_module = mono_dl_open_self (load_error);

if (!internal_module)
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", mono_error_get_message_without_fields (load_error));

mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal.");
mono_error_cleanup (load_error);

return internal_module;
}

static MonoDl *
netcore_lookup_native_library (MonoAssemblyLoadContext *alc, MonoImage *image, const char *scope, guint32 flags)
{
Expand Down
7 changes: 4 additions & 3 deletions src/mono/mono/utils/mono-dl.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,9 @@ fix_libc_name (const char *name)
* mono_dl_open_self:
* \param error pointer to MonoError
*
* Returns a handle to the main program, on android x86 it's not possible to
* call dl_open(null), it returns a null handle, so this function returns RTLD_DEFAULT
* Returns a handle to the main program, on Android it's not possible to
* call dl_open(null) with RTLD_LAZY, it returns a null handle, so this
* function uses RTLD_NOW.
* handle in this platform.
* \p error points to MonoError where an error will be stored in
* case of failure. The error needs to be cleared when done using it, \c mono_error_cleanup.
Expand All @@ -195,7 +196,7 @@ mono_dl_open_self (MonoError *error)
return NULL;
}
mono_refcount_init (module, NULL);
module->handle = RTLD_DEFAULT;
module->handle = dlopen(NULL, RTLD_NOW);
module->dl_fallback = NULL;
module->full_name = NULL;
return module;
Expand Down
15 changes: 7 additions & 8 deletions src/native/libs/System.Native/pal_dynamicload.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,23 @@ void SystemNative_FreeLibrary(void* handle)
dlclose(handle);
}

#ifdef TARGET_ANDROID
void* SystemNative_GetDefaultSearchOrderPseudoHandle(void)
{
return (void*)RTLD_DEFAULT;
}
#else
static void* volatile g_defaultSearchOrderPseudoHandle = NULL;
void* SystemNative_GetDefaultSearchOrderPseudoHandle(void)
{
// Read the value once from the volatile static to avoid reading from memory twice.
void* defaultSearchOrderPseudoHandle = (void*)g_defaultSearchOrderPseudoHandle;
if (defaultSearchOrderPseudoHandle == NULL)
{
#ifdef TARGET_ANDROID
int flag = RTLD_NOW;
#else
int flag = RTLD_LAZY;
#endif

// Assign back to the static as well as the local here.
// We don't need to check for a race between two threads as the value returned by
// dlopen here will always be the same in a given environment.
g_defaultSearchOrderPseudoHandle = defaultSearchOrderPseudoHandle = dlopen(NULL, RTLD_LAZY);
g_defaultSearchOrderPseudoHandle = defaultSearchOrderPseudoHandle = dlopen(NULL, flag);
}
return defaultSearchOrderPseudoHandle;
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;

using Xunit;

public static class MainProgramHandleTests
{
private static IntPtr s_handle;

static MainProgramHandleTests() => NativeLibrary.SetDllImportResolver(typeof(MainProgramHandleTests).Assembly,
(string libraryName, Assembly asm, DllImportSearchPath? dllImportSearchPath) =>
{
if (libraryName == "Self")
{
s_handle = NativeLibrary.GetMainProgramHandle();
Assert.NotEqual(IntPtr.Zero, s_handle);
return s_handle;
}

return IntPtr.Zero;
});

public static int Main()
{
try
{
free(s_handle);
am11 marked this conversation as resolved.
Show resolved Hide resolved
}
catch (Exception e)
{
Console.WriteLine($"Test Failure: {e}");
return 101;
}

return 100;
}

[DllImport("Self")]
private static extern void free(IntPtr arg);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestTargetUnsupported Condition="'$(TargetsWindows)' == 'true' or '$(RuntimeVariant)' == 'monointerpreter'">true</CLRTestTargetUnsupported>
</PropertyGroup>
<ItemGroup>
<Compile Include="MainProgramHandleTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(TestSourceDir)Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions src/tests/issues.targets
Original file line number Diff line number Diff line change
Expand Up @@ -2606,6 +2606,9 @@
<ExcludeList Include = "$(XunitTestBinBase)/Interop/StructMarshalling/ReversePInvoke/MarshalSeqStruct/DelegatePInvoke/DelegatePInvokeTest/**">
<Issue>needs triage</Issue>
</ExcludeList>
<ExcludeList Include = "$(XunitTestBinBase)/Interop/NativeLibrary/MainProgramHandle/**">
<Issue>needs triage</Issue>
</ExcludeList>
<ExcludeList Include = "$(XunitTestBinBase)/JIT/Methodical/eh/basics/throwinfilter_il_d/**">
<Issue>https://github.com/dotnet/runtime/issues/47624</Issue>
</ExcludeList>
Expand Down