socketry / async-http

MIT License
298 stars 45 forks source link

Using a proxy hangs when closing or ends with a warning #144

Closed PMAxelDelsol closed 8 months ago

PMAxelDelsol commented 8 months ago

When trying to use async-http client with a proxy, closing the client hangs indefinitely. Below is a simplified example to reproduce the issue.

# frozen_string_literal: true

require 'async/http/client'
require 'async/http/proxy'

proxy_url = ENV['HTTP_PROXY']
endpoint_url = 'https://httpbingo.org'

proxy_endpoint = Async::HTTP::Endpoint.parse(proxy_url)
proxy_client = Async::HTTP::Client.new(proxy_endpoint)

endpoint = Async::HTTP::Endpoint.parse(endpoint_url)
client = proxy_client.proxied_client(endpoint)

Sync do
  puts 'Calling delay'
  response = client.get('/delay/1')#.read
  puts 'Done delay'
ensure
  client.close
end

puts 'Exit'

Sample run using CONSOLE_LEVEL=debug:

...
Done delay
  1.3s     warn: Async::HTTP::Client: connected to #<Addrinfo: ENV['HTTP_PROXY'] TCP (localhost)>
               | Waiting for Async::HTTP::Protocol::HTTPS pool to drain: #<Async::Pool::Controller(1/∞) 1/4294967295/1>

The issue looks like #37 so I tried to add response.read. Now it ends with a warning:

 1.32s    debug: Async::Reactor 
               | Exiting run-loop because finished.
 1.32s     warn: Async::Pool::Controller: Async::Pool::Controller Gardener
               | Closing resource while still in use!
               | {"resource":"#<Async::HTTP::Protocol::HTTP1::Client:0x00007fbb626d49b0>","usage":1}
 1.32s    debug: Async::Pool::Controller: Async::HTTP::Body::Pipe reader. 
               | Retire #<Async::HTTP::Protocol::HTTP1::Client:0x00007fbb626d49b0>
ioquatix commented 8 months ago

Are you closing the connection?

begin
  response = client.get('/delay/1')
  response.read
ensure
  response.close
end

Are you closing the proxy client?

Async do
  proxy_endpoint = Async::HTTP::Endpoint.parse(proxy_url)
  proxy_client = Async::HTTP::Client.new(proxy_endpoint)

  endpoint = Async::HTTP::Endpoint.parse(endpoint_url)
  client = proxy_client.proxied_client(endpoint)

  # use client
ensure
  client.close
  proxy_client.close
end

I'll try out your code to see if I can reproduce the issue.

PMAxelDelsol commented 8 months ago

Closing the client and the proxy_client (in that order) now waits for the pool to drain and then exit properly.

Thanks for your help !