Skip to content

Commit

Permalink
(PUP-11853) Wait for request completion before closing
Browse files Browse the repository at this point in the history
Before this commit, puppet would attempt to `finish` a
connection in the block passed to an `http.request` function. This
will not work because `finish` sets the `@socket` to nil, and the
net/http request assumes that the `@socket` is set for the duration
of that function. With this change, we mark some state during the
request function that indicates the connection should be closed
after the completion of the `http.request`.
  • Loading branch information
tvpartytonight committed Jul 7, 2023
1 parent c9f17b1 commit aac5d7d
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 4 deletions.
11 changes: 9 additions & 2 deletions lib/puppet/http/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ def execute_streaming(request, options: {}, &block)
apply_auth(request, basic_auth) if redirects.zero?

# don't call return within the `request` block
close_connection_after_request = false
http.request(request) do |nethttp|
response = Puppet::HTTP::ResponseNetHTTP.new(request.uri, nethttp)
begin
Expand All @@ -381,8 +382,7 @@ def execute_streaming(request, options: {}, &block)
retries += 1
if interval
if http.started?
Puppet.debug("Closing connection for #{Puppet::HTTP::Site.from_uri(request.uri)}")
http.finish
close_connection_after_request = true
end
Puppet.warning(_("Sleeping for %{interval} seconds before retrying the request") % { interval: interval })
::Kernel.sleep(interval)
Expand All @@ -404,6 +404,13 @@ def execute_streaming(request, options: {}, &block)

done = true
end
ensure
# Connections cannot be closed inside a block passed to http.request,
# so close it after the function has been completed.
if close_connection_after_request
Puppet.debug("Closing connection for #{Puppet::HTTP::Site.from_uri(request.uri)}")
http.finish
end
end
end

Expand Down
2 changes: 1 addition & 1 deletion spec/unit/http/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -862,8 +862,8 @@ def retry_after(datetime)
# The "with_connection" method is required to yield started connections
allow(pool).to receive(:with_connection).and_yield(http1).and_yield(http2)

expect(http1).to receive(:finish).ordered
expect(::Kernel).to receive(:sleep).with(42).ordered
expect(http1).to receive(:finish).ordered

client.get(uri)
end
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/network/http/connection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,8 @@ def retry_after(datetime)

allow(pool).to receive(:with_connection).and_yield(http1).and_yield(http2)

expect(http1).to receive(:finish).ordered
expect(::Kernel).to receive(:sleep).with(42).ordered
expect(http1).to receive(:finish).ordered

subject.get('/foo')
end
Expand Down

0 comments on commit aac5d7d

Please sign in to comment.