Skip to content
This repository has been archived by the owner on Apr 22, 2022. It is now read-only.

Commit

Permalink
FileLoadException: Add Profiler fix (DataDog#671)
Browse files Browse the repository at this point in the history
Fix FileLoadException: Loading this assembly would produce a different grant set from other instances. (Exception from HRESULT: 0x80131401)

## Problem
### Issue 1
Our CLR Profiler currently assumes that as long as the `Datadog.Trace.ClrProfiler.Managed` assembly has been loaded domain-neutral once, all AppDomains can use that assembly. Under this false assumption, we always instrument domain-neutral assemblies which adds an AssemblyReference to our managed profiler and affects how the CLR shares code between AppDomains.

However, some applications may have BindingRedirect's specified on dependencies of the managed profiler like `System.Net.Http` which can force `Datadog.Trace.ClrProfiler.Managed` to no longer be loaded domain-neutral. When we instrument a domain-neutral assembly with a non-domain-neutral `Datadog.Trace.ClrProfiler.Managed` in one AppDomain and then another AppDomain tries to use the instrumented domain-neutral assembly, the second AppDomain crashes with the FileLoadException.

### Issue 2
Our new mechanism for automatically instrumenting AspNet uses the CLR Profiler to intercept a method call inside `System.Web` to call into `Datadog.Trace.ClrProfiler.Managed`. `System.Web` is always loaded domain-neutral but, as noted above, there are circumstances that can cause our assembly to not be loaded domain-neutral. We need to change the way we invoke the AspNet integration so that the assembly that runs the integration code is always domain-neutral.

## Changes proposed in this pull request:
### Addressing Issue 1
- Modify the profiler to never inject method calls to `Datadog.Trace.ClrProfiler.Managed` if the calling assembly was loaded domain-neutral.

### Addressing Issue 2
- Move basic types like `InterceptMethodAttribute` and friends to a new `Datadog.Trace.ClrProfiler.Managed.Core` that has no external dependencies.
- Move the AspNet integration into a new assembly called `Datadog.Trace.AspNet.Loader` whose only dependencies are `Datadog.Trace.ClrProfiler.Managed.Core` and `System.Web`. This assembly closure guarantees that the assembly will always be loaded domain-neutral. This is now a safe entry point for `System.Web` to call into during application setup. Also, the method responsible for adding the AspNet integration does not wrap any methods (that would require `Sigil`).
- To enable the minimal method call above that is simply called and returns to the caller without wrapping any target method, modify the method replacement infrastructure to support an `action`. The default value is `ReplaceTargetMethod` which performs the usual method replacement as before, but a new action `InsertFirst` will add a call to the method as the first instruction in the matching caller method. When generating `integrations.json`, add checks on the new `InsertFirst` integration methods.

## Consequences
- Fix `Loading this assembly would produce a different grant set from other instances. (Exception from HRESULT: 0x80131401)`
- For ASP.NET applications (or other scenarios where `LoaderOptimizationAttribute=MultiDomainHost`), there may be missing spans from calls between framework assemblies. Affected integrations include:
  - HttpMessageHandler
  - WebRequest
  - Wcf (server)
  • Loading branch information
zacharycmontoya authored and MikeGoldsmith committed Mar 20, 2020
1 parent 389aa82 commit 7f78771
Show file tree
Hide file tree
Showing 29 changed files with 749 additions and 349 deletions.
30 changes: 30 additions & 0 deletions Datadog.Trace.sln
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "linux", "linux", "{7DB68365
createLogPath.sh = createLogPath.sh
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.ClrProfiler.Managed.Core", "src\Datadog.Trace.ClrProfiler.Managed.Core\Datadog.Trace.ClrProfiler.Managed.Core.csproj", "{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.AspNet.Loader", "src\Datadog.Trace.AspNet.Loader\Datadog.Trace.AspNet.Loader.csproj", "{77711FF1-3210-47C8-B104-FD3A680056A4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1110,6 +1114,30 @@ Global
{7E563BF6-47F2-4531-A1CE-FB9445DF3253}.Release|x64.Build.0 = Release|x64
{7E563BF6-47F2-4531-A1CE-FB9445DF3253}.Release|x86.ActiveCfg = Release|x86
{7E563BF6-47F2-4531-A1CE-FB9445DF3253}.Release|x86.Build.0 = Release|x86
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x64.ActiveCfg = Debug|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x64.Build.0 = Debug|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x86.ActiveCfg = Debug|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x86.Build.0 = Debug|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|Any CPU.Build.0 = Release|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x64.ActiveCfg = Release|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x64.Build.0 = Release|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x86.ActiveCfg = Release|Any CPU
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x86.Build.0 = Release|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|x64.ActiveCfg = Debug|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|x64.Build.0 = Debug|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|x86.ActiveCfg = Debug|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|x86.Build.0 = Debug|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|Any CPU.Build.0 = Release|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|x64.ActiveCfg = Release|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|x64.Build.0 = Release|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|x86.ActiveCfg = Release|Any CPU
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1190,6 +1218,8 @@ Global
{7B0822F6-80DE-4B49-8125-93975678D0D5} = {550AE553-2BBB-4021-B55A-137EF31A6B1F}
{C41023C9-65C3-4FB3-9053-4DE963A81500} = {550AE553-2BBB-4021-B55A-137EF31A6B1F}
{7E563BF6-47F2-4531-A1CE-FB9445DF3253} = {AA6F5582-3B71-49AC-AA39-8F7815AC46BE}
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB}
{77711FF1-3210-47C8-B104-FD3A680056A4} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.AspNet.dll"
KeyPath="yes" Checksum="yes" Assembly=".net"/>
</Component>
<Component Win64="$(var.Win64)">
<File Id="net45_GAC_Datadog.Trace.AspNet.Loader.dll"
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.AspNet.Loader.dll"
KeyPath="yes" Checksum="yes" Assembly=".net"/>
</Component>
<Component Win64="$(var.Win64)">
<File Id="net45_GAC_Datadog.Trace.ClrProfiler.Managed.Core.dll"
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.ClrProfiler.Managed.Core.dll"
KeyPath="yes" Checksum="yes" Assembly=".net"/>
</Component>
<Component Win64="$(var.Win64)">
<File Id="net45_GAC_Datadog.Trace.ClrProfiler.Managed.dll"
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.ClrProfiler.Managed.dll"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.AspNet.dll"
KeyPath="yes" Checksum="yes"/>
</Component>
<Component Win64="$(var.Win64)">
<File Id="net45_Datadog.Trace.AspNet.Loader.dll"
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.AspNet.Loader.dll"
KeyPath="yes" Checksum="yes"/>
</Component>
<Component Win64="$(var.Win64)">
<File Id="net45_Datadog.Trace.ClrProfiler.Managed.Core.dll"
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.ClrProfiler.Managed.Core.dll"
KeyPath="yes" Checksum="yes"/>
</Component>
<Component Win64="$(var.Win64)">
<File Id="net45_Datadog.Trace.ClrProfiler.Managed.dll"
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.ClrProfiler.Managed.dll"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
Source="$(var.ManagedDllPath)\net461\Datadog.Trace.AspNet.dll"
KeyPath="yes" Checksum="yes"/>
</Component>
<Component Win64="$(var.Win64)">
<File Id="net461_Datadog.Trace.AspNet.Loader.dll"
Source="$(var.ManagedDllPath)\net461\Datadog.Trace.AspNet.Loader.dll"
KeyPath="yes" Checksum="yes"/>
</Component>
<Component Win64="$(var.Win64)">
<File Id="net461_Datadog.Trace.ClrProfiler.Managed.Core.dll"
Source="$(var.ManagedDllPath)\net461\Datadog.Trace.ClrProfiler.Managed.Core.dll"
KeyPath="yes" Checksum="yes"/>
</Component>
<Component Win64="$(var.Win64)">
<File Id="net461_Datadog.Trace.ClrProfiler.Managed.dll"
Source="$(var.ManagedDllPath)\net461\Datadog.Trace.ClrProfiler.Managed.dll"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<?include $(sys.CURRENTDIR)\Config.wxi?>
<Fragment>
<ComponentGroup Id="Files.Managed.NetStandard20" Directory="netstandard2.0">
<Component Win64="$(var.Win64)">
<File Id="netstandard20_Datadog.Trace.ClrProfiler.Managed.Core.dll"
Source="$(var.ManagedDllPath)\netstandard2.0\Datadog.Trace.ClrProfiler.Managed.Core.dll"
KeyPath="yes" Checksum="yes"/>
</Component>
<Component Win64="$(var.Win64)">
<File Id="netstandard20_Datadog.Trace.ClrProfiler.Managed.dll"
Source="$(var.ManagedDllPath)\netstandard2.0\Datadog.Trace.ClrProfiler.Managed.dll"
Expand Down
Loading

0 comments on commit 7f78771

Please sign in to comment.