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

Fix memory leak in the curb instrumentation #1518

Merged
merged 1 commit into from
Oct 4, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions lib/new_relic/agent/instrumentation/curb/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ module Instrumentation
module Curb
module Easy
attr_accessor :_nr_instrumented,
:_nr_failure_instrumented,
:_nr_http_verb,
:_nr_header_str,
:_nr_original_on_header,
Expand Down Expand Up @@ -157,13 +156,16 @@ def install_completion_callback(request, wrapped_response, segment)
# NOTE: on_failure is not always called, so we're not always
# unhooking the callback. No harm/no foul in production, but
# definitely something to beware of if debugging callback issues
# _nr_failure_instrumented exists to prevent infinitely chaining
# @__newrelic_original_callback exists to prevent infinitely chaining
# our on_failure callback hook.
def install_failure_callback(request, wrapped_response, segment)
return if request._nr_failure_instrumented
original_callback = request.on_failure
nr_original_callback = original_callback.instance_variable_get(:@__newrelic_original_callback)
original_callback = nr_original_callback || original_callback

request._nr_original_on_failure = original_callback
request.on_failure do |failed_request, error|

newrelic_callback = proc do |failed_request, error|
begin
if segment
noticible_error = NewRelic::Agent::NoticibleError.new(error[0].name, error[-1])
Expand All @@ -173,8 +175,10 @@ def install_failure_callback(request, wrapped_response, segment)
original_callback.call(failed_request, error) if original_callback
remove_failure_callback(failed_request)
end
request._nr_failure_instrumented = true
end
newrelic_callback.instance_variable_set(:@__newrelic_original_callback, original_callback)

request.on_failure(&newrelic_callback)
end

# on_failure callbacks cannot be removed in the on_complete
Expand All @@ -191,7 +195,6 @@ def remove_instrumentation_callbacks(request)
# fires before the on_failure callback.
def remove_failure_callback(request)
request.on_failure(&request._nr_original_on_failure)
request._nr_failure_instrumented = false
end

private
Expand Down