-
Notifications
You must be signed in to change notification settings - Fork 147
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
fix stack overflow when overriding HttpClientHandler.SendAsync() #367
Conversation
…call's opcode (value not used yet)
…pcode argument to emit the correct IL
084b4f8
to
1e5e290
Compare
@@ -329,18 +336,22 @@ internal static class DynamicMethodBuilder<TDelegate> | |||
} | |||
} | |||
|
|||
if (methodInfo.IsStatic) | |||
if (callOpCode == OpCodeValue.Call || methodInfo.IsStatic) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where we use the new opcode value when emitting IL. Most integrations will still pass the default opcode (CALLVIRT
), so we still check if it's a static method and use CALL
.
// additional arguments for the wrapper method | ||
ILRewriterWrapper rewriter_wrapper(&rewriter); | ||
rewriter_wrapper.SetILPosition(pInstr); | ||
rewriter_wrapper.LoadInt32(pInstr->m_opcode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where we insert the original call's opcode value into the execution stack before replacing the method call.
var tokenSource = cancellationTokenSource as CancellationTokenSource; | ||
var cancellationToken = tokenSource?.Token ?? CancellationToken.None; | ||
var callOpCode = (OpCodeValue)opCode; | ||
var handlerType = typeof(HttpClientHandler); // Note the HttpClientHandler to match the method call we replaced |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you rename handlerType
to httpClientHandlerType
to be a little more specific about the meaning of the variable? I was confused initially because I thought handlerType
meant handler.GetType()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed that and a few more in feffd93.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That helps a lot, thanks!
var tokenSource = cancellationTokenSource as CancellationTokenSource; | ||
var cancellationToken = tokenSource?.Token ?? CancellationToken.None; | ||
var callOpCode = (OpCodeValue)opCode; | ||
var handlerType = typeof(HttpMessageHandler); // Note the HttpMessageHandler to match the method call we replaced |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment here, can we do httpMessageHandlerType
instead of just handlerType
for the variable name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed in the same commit as the previous comment.
Moving forward with this then, our convention will be that all wrapper methods must have |
samples/Directory.Build.props
Outdated
@@ -17,7 +17,7 @@ | |||
</ItemGroup> | |||
|
|||
<ItemGroup> | |||
<None Include="..\..\src\Datadog.Trace.ClrProfiler.Native\bin\$(Configuration)\$(Platform)\**" | |||
<None Include="..\..\src\Datadog.Trace.ClrProfiler.Native\bin\$(Configuration)\$(Platform)\*.dll;..\..\src\Datadog.Trace.ClrProfiler.Native\bin\$(Configuration)\$(Platform)\*.so" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this disregard pdb files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! I added the pdb files in 2f28ef3.
@colin-higgins: (sorry, I couldn't reply directly to your comment)
Yes. As of this PR only the
Good point! I added a test in ba059d4. |
Fix
StackOverflowException
whenHttpClientHandler.SendAsync()
is overridden by a method that calls the base method. See #351.For example:
This PR makes changes that affect all integrations:
CALLVIRT
to keep the current behaviorChanges to
HttpMessageHandlerIntegration
:HttpMessageHandler.SendAsync()
andHttpClientHandler.SendAsync()
CALL
orCALLVIRT
) when calling original method