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

Load the managed profiler code as early as possible #462

Merged
merged 54 commits into from
Aug 12, 2019

Conversation

zacharycmontoya
Copy link
Contributor

Changes proposed in this pull request:

  • Create a new .NET assembly that contains logic to attempt an a load of the Datadog.Trace.ClrProfiler.Managed assembly (with exception handling)
  • Embed the new .NET assembly into the native profiler image
  • Load the helper assembly into the caller's app domain by reading the assembly into a byte array and calling the byte array overload of AppDomain.Load(byte[], byte[]) -- the second byte array reads the symbols
  • Only on the first JITCompilationStarted event, call into a dynamically generated method to attempt the assembly load

Fixes:

  • Issues when trying to instrument applications when the managed profiler assembly cannot be located by the runtime.
  • Issues when trying to reference the managed profiler assembly from a domain-neutral assembly when the managed profiler assembly is not domain-neutral.

@DataDog/apm-dotnet

@zacharycmontoya zacharycmontoya added status:work-in-progress Actively worked on. If this is a PR, no review needed yet. WIP. area:native-library Automatic instrumentation native C++ code (Datadog.Trace.ClrProfiler.Native) labels Aug 5, 2019
@zacharycmontoya zacharycmontoya self-assigned this Aug 5, 2019
@zacharycmontoya zacharycmontoya force-pushed the zach/security-grant-fix branch from f3c0f87 to 2192e98 Compare August 8, 2019 00:26
@zacharycmontoya zacharycmontoya removed the status:work-in-progress Actively worked on. If this is a PR, no review needed yet. WIP. label Aug 8, 2019
@zacharycmontoya zacharycmontoya marked this pull request as ready for review August 8, 2019 17:35
@zacharycmontoya zacharycmontoya requested a review from a team as a code owner August 8, 2019 17:35
@zacharycmontoya
Copy link
Contributor Author

This passes the Linux integration tests 👍

One last thing I'd like to do before merging (and addressing PR-related feedback of course) is to enable the Smoke tests for Windows, since this feature only hits Windows right now.

{
try
{
Assembly.Load(new AssemblyName("Datadog.Trace.ClrProfiler.Managed, Version=1.6.0.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb"));
Copy link
Member

Choose a reason for hiding this comment

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

We may want to tie this to some sort of constant if possible. Is the current idea to update this manually for every release? I'm okay with that for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh yeah, that was an item I wanted to revisit. I hard-coded it to start but I would much prefer making it more automatic if we can figure out a good way to do that.

Copy link
Member

Choose a reason for hiding this comment

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

At worst, tests will fail if we miss it currently.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The scarier part is if we miss this on the version update...maybe we should also enable running the smoke tests for the packaging step?

Copy link
Member

Choose a reason for hiding this comment

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

Won't the tests fail on the version update PR if we miss this piece?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like our integration tests don't catch this because the changes only apply to Windows and our smoke tests (Category="Smoke") don't count spans. I'll try enabling one Category="EndToEnd" (I think the HttpMessageHandler) that doesn't have external dependencies

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Heh yeah I got the Datadog.Trace.ClrProfiler.IntegrationTests.HttpClientTests.HttpClient to pass with the correct assembly name but fail with the incorrect assembly name. I'll get this into this PR 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently blocked on adding this until the following issue is fixed with the .NET Core SDK installer task ☹️

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay I just pushed 00c0090 which runs the HttpClientTests E2E tests on Windows. I was able to show on a separate branch that this fails when the string in the Loader fails. That's because we expect at least one span in the integration tests and we don't end up sending any in this scenario

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll leave this comment chain as unresolved to indicate that there's still some work left here to do, but I don't think I'll be changing this on this PR, if that's fine with you guys.

@colin-higgins colin-higgins mentioned this pull request Aug 9, 2019
2 tasks
@zacharycmontoya
Copy link
Contributor Author

zacharycmontoya commented Aug 9, 2019

I'm going to bulk resolve all of Colin's L"string" suggestions. The metadata interfaces require LPCWSTR arguments (which is expected to be 16-bit because of the definitions inside CoreCLR) but on Linux the wchar_t type is defined as 32-bits. For that reason, I needed to use the c_str() calls to make the conversions correct for both OS'es.

Run StackExchangeRedisStackOverflowExceptionSmokeTest only on non-Windows platforms
…ate.CoreLib, and save the module id's for the corelib module and the managed profiler.
…dows integration test failures.

In MockTracerAgent, save the request headers instead of the requests themselves.
The requests get disposed when the response is closed, causing ObjectDisposedExceptions to be thrown.
@zacharycmontoya zacharycmontoya force-pushed the zach/security-grant-fix branch from 38dff6c to 4fd78ba Compare August 12, 2019 19:04
// proper string for CreateInstance to successfully call
#ifdef _WIN32
LPCWSTR load_helper_str =
L"Datadog.Trace.ClrProfiler.Managed.Loader.Startup";
Copy link
Member

@lucaspimentel lucaspimentel Aug 12, 2019

Choose a reason for hiding this comment

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

Did you try this with "some_string"_W? That should work on both platforms. See pal.h.

(If this works, no need to fix in this PR. We can look into this when working on the Linux implementation.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had issues using "string"_W working on both Windows and Linux. Let me follow up on this when I get the Linux implementation up and running.

@zacharycmontoya zacharycmontoya merged commit 4ce932f into develop Aug 12, 2019
@zacharycmontoya zacharycmontoya deleted the zach/security-grant-fix branch August 12, 2019 22:30
@colin-higgins colin-higgins added this to the 1.6.1 milestone Aug 13, 2019
zacharycmontoya added a commit that referenced this pull request Aug 29, 2019
The main mechanism for loading the managed profiler code was introduced in #462 (commit 4ce932f).

This PR turns on the feature for Linux. The main components are embedding the resources into the shared library, retrieving the embedded resources in the native profiler, and adding the correct PInvoke from the injected assembly load.
macrogreg pushed a commit that referenced this pull request Aug 20, 2021
Implementation Changes (Enabled only on Windows for now):
* Creates a new library called Datadog.Trace.ClrProfiler.Managed.Loader that is embedded in the native profiler image. When the type is loaded, it has a static constructor to call Assembly.Load on our managed profiler code in a try-catch block.

* On first JITCompilationStarted, dynamically emit IL to load the Datadog.Trace.ClrProfiler.Managed.Loader assembly and attempt to load the managed profiler code.

* Change the native profiler so no edits are made in the JITCompilationStarted event unless the managed profiler code is already loaded.

* Keep track of the app domain of mscorlib, the managed profiler assembly, and the method caller's assembly and do not edit the IL of a method if referencing the managed profiler assembly would invalidate the caller's domain-neutral assembly reference closure.


Tests and Results:
* Enable a subset of integration tests on Windows. Smoke tests and the E2E HttpClientTests are now run on Windows.

* Fixes System.IO.FileNotFoundException when trying to load (Assembly.Load) the managed profiler but it cannot be found. Adds a smoke test called AssemblyLoad.FileNotFoundException to verify the behavior (Windows-only for now).

* Fixes System.IO.FileLoadException: Loading this assembly would produce a different grant set from other instances. Adds a smoke test called SecurityGrant.FileNotFoundException to verify the behavior (only runs on .NET Framework).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:native-library Automatic instrumentation native C++ code (Datadog.Trace.ClrProfiler.Native) os:windows
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants