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

Commit 7f78771

Browse files
zacharycmontoyaMikeGoldsmith
authored andcommitted
FileLoadException: Add Profiler fix (DataDog#671)
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)
1 parent 389aa82 commit 7f78771

29 files changed

+749
-349
lines changed

Datadog.Trace.sln

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "linux", "linux", "{7DB68365
312312
createLogPath.sh = createLogPath.sh
313313
EndProjectSection
314314
EndProject
315+
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}"
316+
EndProject
317+
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}"
318+
EndProject
315319
Global
316320
GlobalSection(SolutionConfigurationPlatforms) = preSolution
317321
Debug|Any CPU = Debug|Any CPU
@@ -1110,6 +1114,30 @@ Global
11101114
{7E563BF6-47F2-4531-A1CE-FB9445DF3253}.Release|x64.Build.0 = Release|x64
11111115
{7E563BF6-47F2-4531-A1CE-FB9445DF3253}.Release|x86.ActiveCfg = Release|x86
11121116
{7E563BF6-47F2-4531-A1CE-FB9445DF3253}.Release|x86.Build.0 = Release|x86
1117+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1118+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
1119+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x64.ActiveCfg = Debug|Any CPU
1120+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x64.Build.0 = Debug|Any CPU
1121+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x86.ActiveCfg = Debug|Any CPU
1122+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x86.Build.0 = Debug|Any CPU
1123+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
1124+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|Any CPU.Build.0 = Release|Any CPU
1125+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x64.ActiveCfg = Release|Any CPU
1126+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x64.Build.0 = Release|Any CPU
1127+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x86.ActiveCfg = Release|Any CPU
1128+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x86.Build.0 = Release|Any CPU
1129+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1130+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
1131+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|x64.ActiveCfg = Debug|Any CPU
1132+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|x64.Build.0 = Debug|Any CPU
1133+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|x86.ActiveCfg = Debug|Any CPU
1134+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Debug|x86.Build.0 = Debug|Any CPU
1135+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
1136+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|Any CPU.Build.0 = Release|Any CPU
1137+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|x64.ActiveCfg = Release|Any CPU
1138+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|x64.Build.0 = Release|Any CPU
1139+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|x86.ActiveCfg = Release|Any CPU
1140+
{77711FF1-3210-47C8-B104-FD3A680056A4}.Release|x86.Build.0 = Release|Any CPU
11131141
EndGlobalSection
11141142
GlobalSection(SolutionProperties) = preSolution
11151143
HideSolutionNode = FALSE
@@ -1190,6 +1218,8 @@ Global
11901218
{7B0822F6-80DE-4B49-8125-93975678D0D5} = {550AE553-2BBB-4021-B55A-137EF31A6B1F}
11911219
{C41023C9-65C3-4FB3-9053-4DE963A81500} = {550AE553-2BBB-4021-B55A-137EF31A6B1F}
11921220
{7E563BF6-47F2-4531-A1CE-FB9445DF3253} = {AA6F5582-3B71-49AC-AA39-8F7815AC46BE}
1221+
{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB}
1222+
{77711FF1-3210-47C8-B104-FD3A680056A4} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB}
11931223
EndGlobalSection
11941224
GlobalSection(ExtensibilityGlobals) = postSolution
11951225
SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F}

deploy/Datadog.Trace.ClrProfiler.WindowsInstaller/Files.Managed.Net45.GAC.wxs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.AspNet.dll"
1111
KeyPath="yes" Checksum="yes" Assembly=".net"/>
1212
</Component>
13+
<Component Win64="$(var.Win64)">
14+
<File Id="net45_GAC_Datadog.Trace.AspNet.Loader.dll"
15+
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.AspNet.Loader.dll"
16+
KeyPath="yes" Checksum="yes" Assembly=".net"/>
17+
</Component>
18+
<Component Win64="$(var.Win64)">
19+
<File Id="net45_GAC_Datadog.Trace.ClrProfiler.Managed.Core.dll"
20+
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.ClrProfiler.Managed.Core.dll"
21+
KeyPath="yes" Checksum="yes" Assembly=".net"/>
22+
</Component>
1323
<Component Win64="$(var.Win64)">
1424
<File Id="net45_GAC_Datadog.Trace.ClrProfiler.Managed.dll"
1525
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.ClrProfiler.Managed.dll"

deploy/Datadog.Trace.ClrProfiler.WindowsInstaller/Files.Managed.Net45.wxs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.AspNet.dll"
1111
KeyPath="yes" Checksum="yes"/>
1212
</Component>
13+
<Component Win64="$(var.Win64)">
14+
<File Id="net45_Datadog.Trace.AspNet.Loader.dll"
15+
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.AspNet.Loader.dll"
16+
KeyPath="yes" Checksum="yes"/>
17+
</Component>
18+
<Component Win64="$(var.Win64)">
19+
<File Id="net45_Datadog.Trace.ClrProfiler.Managed.Core.dll"
20+
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.ClrProfiler.Managed.Core.dll"
21+
KeyPath="yes" Checksum="yes"/>
22+
</Component>
1323
<Component Win64="$(var.Win64)">
1424
<File Id="net45_Datadog.Trace.ClrProfiler.Managed.dll"
1525
Source="$(var.ManagedDllPath)\net45\Datadog.Trace.ClrProfiler.Managed.dll"

deploy/Datadog.Trace.ClrProfiler.WindowsInstaller/Files.Managed.Net461.wxs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010
Source="$(var.ManagedDllPath)\net461\Datadog.Trace.AspNet.dll"
1111
KeyPath="yes" Checksum="yes"/>
1212
</Component>
13+
<Component Win64="$(var.Win64)">
14+
<File Id="net461_Datadog.Trace.AspNet.Loader.dll"
15+
Source="$(var.ManagedDllPath)\net461\Datadog.Trace.AspNet.Loader.dll"
16+
KeyPath="yes" Checksum="yes"/>
17+
</Component>
18+
<Component Win64="$(var.Win64)">
19+
<File Id="net461_Datadog.Trace.ClrProfiler.Managed.Core.dll"
20+
Source="$(var.ManagedDllPath)\net461\Datadog.Trace.ClrProfiler.Managed.Core.dll"
21+
KeyPath="yes" Checksum="yes"/>
22+
</Component>
1323
<Component Win64="$(var.Win64)">
1424
<File Id="net461_Datadog.Trace.ClrProfiler.Managed.dll"
1525
Source="$(var.ManagedDllPath)\net461\Datadog.Trace.ClrProfiler.Managed.dll"

deploy/Datadog.Trace.ClrProfiler.WindowsInstaller/Files.Managed.NetStandard20.wxs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
<?include $(sys.CURRENTDIR)\Config.wxi?>
66
<Fragment>
77
<ComponentGroup Id="Files.Managed.NetStandard20" Directory="netstandard2.0">
8+
<Component Win64="$(var.Win64)">
9+
<File Id="netstandard20_Datadog.Trace.ClrProfiler.Managed.Core.dll"
10+
Source="$(var.ManagedDllPath)\netstandard2.0\Datadog.Trace.ClrProfiler.Managed.Core.dll"
11+
KeyPath="yes" Checksum="yes"/>
12+
</Component>
813
<Component Win64="$(var.Win64)">
914
<File Id="netstandard20_Datadog.Trace.ClrProfiler.Managed.dll"
1015
Source="$(var.ManagedDllPath)\netstandard2.0\Datadog.Trace.ClrProfiler.Managed.dll"

0 commit comments

Comments
 (0)