diff --git a/lib/async/http/faraday/clients.rb b/lib/async/http/faraday/clients.rb index 3e8d1a8..b9e5c54 100644 --- a/lib/async/http/faraday/clients.rb +++ b/lib/async/http/faraday/clients.rb @@ -177,10 +177,10 @@ def with_proxied_client(proxy_endpoint, endpoint, &block) # This will close all clients associated with all threads. def close Thread.list.each do |thread| - if clients = thread[@key] - clients.close + if clients = thread.thread_variable_get(@key) + thread.thread_variable_set(@key, nil) - thread[@key] = nil + clients.close end end end diff --git a/releases.md b/releases.md index 0ac1a16..142e418 100644 --- a/releases.md +++ b/releases.md @@ -1,5 +1,9 @@ # Releases +## Unreleased + + - Fix memory leak in `Async::HTTP::Faraday::PerThreadPersistentClients` by ensuring that the `close` method is called on all clients when the adapter is closed. + ## v0.21.0 ### Improved support for `timeout` and `read_timeout`. diff --git a/test/async/http/faraday/clients.rb b/test/async/http/faraday/clients.rb index a4a90e6..1adc526 100644 --- a/test/async/http/faraday/clients.rb +++ b/test/async/http/faraday/clients.rb @@ -57,4 +57,33 @@ end end end + + with "#close" do + it "closes all clients" do + endpoint = Async::HTTP::Endpoint.parse("http://example.com") + client = clients.make_client(endpoint) + expect(client).to receive(:close) + + clients.close + end + end +end + +describe Async::HTTP::Faraday::PerThreadPersistentClients do + let(:clients) {subject.new} + + with "#close" do + it "closes all clients" do + endpoint = Async::HTTP::Endpoint.parse("http://example.com") + closed = false + + clients.with_client(endpoint) do |client| + expect(client).to receive(:close, &proc{closed = true}) + end + + expect(closed).to be == false + clients.close + expect(closed).to be == true + end + end end