Skip to content

[DllImport] fails despite the DLL is already loaded #58601

Open
@Const-me

Description

@Const-me

Found on ARM64 Alpine Linux.

Only tested with .NET 6 but I would expect the bug to affect the rest of the Alpine Linux runtimes too.

Steps to reproduce

Use gcc to compile a C DLL which exports a function. Place the compiled DLL into different folder, such as linux-musl-arm64 subfolder.

Use the following code to load it from absolute path:

[DllImport( "libdl" )]
static extern IntPtr dlopen( [In, MarshalAs( UnmanagedType.LPUTF8Str )] string fileName, int flags );
const int RTLD_NOW = 0x002;

string iLoadLibrary.fileName( string dll ) => $"lib{ dll }.so";

void iLoadLibrary.load( string dll )
{
	IntPtr handle = dlopen( dll, RTLD_NOW );
	if( handle != IntPtr.Zero )
		return;
	throw new ApplicationException( $"dlopen failed to load { Path.GetFileName( dll ) }" );
}

In another class, consume the function exported from the DLL with [DllImport] attribute.

In the main function, call iLoadLibrary.load with absolute path to the *.so file, then call the imported function.

Compile and run the .NET app.

Expected Behavior

Should work like on the rest of the platforms (Windows, non-Alpine Linux including ARM)

Actual Behavior

Exception saying it’s unable to find my DLL, despite already loaded into the current process with dlopen.

Couple more notes.

I did try to copy the DLL into the same location where the C# DLL is, worked fine that way. Can’t do that in production because I support multiple architectures, and for security reasons the process does not have permissions to write its own binaries.

If you don’t know how to enumerate loaded native DLLs on Linux, read this. BTW, that’s how I’m detecting musl libc on Linux, by looking for the loaded ld-musl-* DLL.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions