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

Linking native libraries into superhost #38684

Merged
merged 20 commits into from
Jul 16, 2020
Merged

Conversation

VSadov
Copy link
Member

@VSadov VSadov commented Jul 1, 2020

Related to: #37119

This change results in singlefilehost to embed the following native libraries on Linux:

  • libSystem.Native
  • libSystem.IO.Compression.Native
  • libSystem.Net.Security.Native
  • libSystem.Security.Cryptography.Native.OpenSsl

@VSadov VSadov added NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) NO-REVIEW Experimental/testing PR, do NOT review it labels Jul 1, 2020
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jul 1, 2020
@jkotas
Copy link
Member

jkotas commented Jul 2, 2020

delete exports file

Is this going to export everything - is it going to expose us to problems with colliding symbols like #38189 ?

@VSadov
Copy link
Member Author

VSadov commented Jul 2, 2020

Yes, removing export file, in theory would export what the libraries would be exporting by themselves.
It could be possible to get duplicates if more than one library export same named methods - like "Initialize()". I hope we do not have those.

I want to see first if the whole thing works at all. If there are other reasons why this may not work - for example on OSX or MUSL, it is better to know that earlier.

@jkotas
Copy link
Member

jkotas commented Jul 2, 2020

in theory

It is not a theoretical risk. We had number of crashing bugs around this.

@VSadov VSadov force-pushed the nativeBundle branch 2 times, most recently from c94ea93 to 77bcb18 Compare July 7, 2020 01:54
@VSadov VSadov force-pushed the nativeBundle branch 3 times, most recently from 4ee534c to 8cd0844 Compare July 13, 2020 17:06
@VSadov VSadov removed NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) NO-REVIEW Experimental/testing PR, do NOT review it labels Jul 13, 2020
@VSadov VSadov force-pushed the nativeBundle branch 3 times, most recently from 81a5cae to dc532a0 Compare July 14, 2020 18:02
@VSadov VSadov marked this pull request as ready for review July 14, 2020 18:04
@VSadov VSadov changed the title [WIP]Linking native libraries into superhost Linking native libraries into superhost Jul 14, 2020
for (int i = 0; i < count; ++i)
{
const char* match = toRedirect[i];
int matchLength = strlen(match);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lengths should be compile time constants and have no need to be computed at runtime. This should be simple to handle above.

Copy link
Member Author

@VSadov VSadov Jul 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Originally this was supposed to be more dynamic. Now that only Linux is supported, this can be simplified a bit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just call strcmp ?

Copy link
Member Author

@VSadov VSadov Jul 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure how fast we need to be with this check.
I can as well switch on a strlen against 4 known values and strcmp accordingly, but it might be that just strcmp is good enough. These are relatively short strings.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it looks like we try to support some/path/System.Native.so as well, then knowing the length is needed.
In C# this would be EndsWith.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like we try to support some/path/System.Native.so

Is it a good idea to support this? If somebody specifies a path, I would expect that we will load the stuff from that path and do not do any single-file redirects.

Copy link
Member

@jkotas jkotas Jul 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought: The Unix PAL may be a wrong places for these redirects. Doing the redirects in PAL would not work on Windows - there is no Unix PAL on Windows. Would it be better to do these redirects in LoadNativeLibraryBySearch ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not supporting path (just using strcmp) works. I am not sure what was the intent to support path as well. Would we ever get a path for these libraries?

LoadNativeLibraryBySearch seems like a better place to put the shim. Especially when supporting Windows.
I did not know that this entry point existed. I wonder if there are caveats with placing shim there. Maybe we should do that separately.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of this came from quick&dirty prototype that was put together without much thinking. The point of this work is to do it right (tm).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the library load redirection shim to LoadNativeLibraryBySearch

src/installer/corehost/cli/apphost/static/CMakeLists.txt Outdated Show resolved Hide resolved
generate_exports_file(${DEF_SOURCES} ${EXPORTS_FILE})
if(CLR_CMAKE_TARGET_OSX)
LIST(APPEND NATIVE_LIBS
${NATIVE_LIBS_LOCATION}/libSystem.Security.Cryptography.Native.Apple.a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we adding this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would be adding this on OSX, since OSX has one more native library.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that should not be part of this PR as we don't add any other static libraries for OSX, right? That's what I was asking about.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had two options - remove the non-linux code completely or keep it somehow, but not run. There was a suggestion above to comment it out and put explanation why (we kind of have an explanation already).
Would that be better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this cmake code path is now Linux only.

Copy link
Member Author

@VSadov VSadov Jul 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will comment out the non-Linux code. It seems indeed confusing to leave it as this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer just completely removing this whole if. It is very confusing and after we enable OSX, it would not be correct either (the libSystem.Security.Cryptography.Native.OpenSsl.a is not for OSX).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I will remove this part.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed a change. Please take a look if it is what you expected.

W("System.Security.Cryptography.Native.OpenSsl.so")
};

int count = sizeof(toRedirect) / sizeof(toRedirect[0]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: sizeof(toRedirect) / sizeof(toRedirect[0]) -> lengthof(toRedirect)

Feel free to defer this change until post P8.

@@ -592,6 +592,11 @@ PALAPI
PAL_LoadLibraryDirect(
IN LPCWSTR lpLibFileName)
{
if (!lpLibFileName && g_running_in_exe)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this warrants a comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a helper that is self-explanatory ShouldRedirectToCurrentLibrary. Just made the code call that.

@@ -592,6 +604,11 @@ PALAPI
PAL_LoadLibraryDirect(
IN LPCWSTR lpLibFileName)
{
if (ShouldRedirectToCurrentLibrary(lpLibFileName))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not need to check g_running_in_exe at all. We should be able to return dlopen(NULL...) for lpLibFileName == NULL uncoditionally.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is code following this treating NULL and "" as error conditions. I thought there is some value to fail on unexpected NULL.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So should the g_running_in_exe be removed in the ShouldRedirectToCurrentLibrary helper?

If the check is unnecessary, I guess it is unnecessary in either case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually - I think the g_running_in_exe check could be an assert.

@@ -592,6 +604,11 @@ PALAPI
PAL_LoadLibraryDirect(
IN LPCWSTR lpLibFileName)
{
if (ShouldRedirectToCurrentLibrary(lpLibFileName))
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This should be after the ENTRY macro to follow PAL conventions

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also should not return without LOGEXIT and PERF_EXIT . Fixed that too.

@@ -603,6 +615,12 @@ PAL_LoadLibraryDirect(
lpLibFileName ? lpLibFileName : W16_NULLSTRING,
lpLibFileName ? lpLibFileName : W16_NULLSTRING);

if (ShouldRedirectToCurrentLibrary(lpLibFileName))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I do not think that the assert has much value. I would make this just libraryNameOrPath == NULL.

Copy link
Member Author

@VSadov VSadov Jul 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had doubts that we may be using NULL on this codepath for something else, perhaps transiently, especially when I saw failures on Linux arm/arm64 related to "kernel32.dll not found".
There was a thought - maybe NULL name is involved in that scenario. However, having this assert I knew that it cannot be so. It turned out something unrelated to this change and passed reliably after rebasing.

I guess at this point we know fairly well that NULL is not used for anything else, so assert can be removed.

…Library will be always considered self-referring.
@@ -51,6 +51,9 @@
#include "clr/fs/path.h"
using namespace clr::fs;

// Specifies whether coreclr is embedded or standalone
extern bool g_coreclr_embedded;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are we setting this variable? I cannot see it in this PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the variable was introduced when we did coreclr embedding (previous PR of this series). It relies on coreclr mergeable knowing this fact at compile time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// g_coreclr_embedded indicates that coreclr is linked directly into the program

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks for the details, I've missed this one, I somehow thought we had just the g_running_in_exe.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

g_running_in_exe is the PAL mirror of g_coreclr_embedded, since it can't see g_coreclr_embedded directly.

@VSadov
Copy link
Member Author

VSadov commented Jul 16, 2020

Assert failure(PID 22 [0x00000016], Thread: 122 [0x007a]): Assertion failed '!foundDiff' in 'OpenSsl:GetSslError(Microsoft.Win32.SafeHandles.SafeSslHandle,int,byref):int' during 'Linear scan register alloc' (IL size 99)

File: /__w/1/s/src/coreclr/src/jit/lsra.cpp Line: 2262

This is in an ordinary (not singlefile) Library test on Linux musl arm64
It does not look like it could be related to the change

@VSadov
Copy link
Member Author

VSadov commented Jul 16, 2020

Same assert failed in #39464 as well

@VSadov
Copy link
Member Author

VSadov commented Jul 16, 2020

Logged a bug about the LSRA assert - #39484

@VSadov
Copy link
Member Author

VSadov commented Jul 16, 2020

I think this is ok for merging. Thanks everyone for reviewing!!!!

@VSadov VSadov merged commit ef6c035 into dotnet:master Jul 16, 2020
@VSadov VSadov deleted the nativeBundle branch July 16, 2020 23:29
VSadov added a commit to VSadov/runtime that referenced this pull request Jul 17, 2020
* native libs location

* pass artifacts locations as CMake variables.

* Link native libs

* use LibrariesConfiguration to discover libraries artifacts

* redirect to current exe

* remove bundled binaries from the  netcoreapp/pkg

* delete exports file

* no bundling of native libs on OSX

* only link native libs on Linux

* Support linking of coreclr on Linux only

* PR feedback

* move the shim to dllimport.cpp

* Use library names vs. file names

* removed ShouldRedirectToCurrentLibrary. NULL library name in PAL_LoadLibrary will be always considered self-referring.
jeffschwMSFT pushed a commit that referenced this pull request Jul 17, 2020
* native libs location

* pass artifacts locations as CMake variables.

* Link native libs

* use LibrariesConfiguration to discover libraries artifacts

* redirect to current exe

* remove bundled binaries from the  netcoreapp/pkg

* delete exports file

* no bundling of native libs on OSX

* only link native libs on Linux

* Support linking of coreclr on Linux only

* PR feedback

* move the shim to dllimport.cpp

* Use library names vs. file names

* removed ShouldRedirectToCurrentLibrary. NULL library name in PAL_LoadLibrary will be always considered self-referring.
@ghost ghost locked as resolved and limited conversation to collaborators Dec 8, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants