-
-
Notifications
You must be signed in to change notification settings - Fork 52
Description
I'm trying to update the async gem from v1.x to v2.x, which async-http gem depends on.
fluent/fluentd#3842
Then, I found a problem that Async HTTP Server stops responding If I use the async gem and cool.io gem under Windows.
It works well under Linux and macOS even if I use them.
Curiously, if I removed https://github.com/socketry/cool.io/blame/2735948698687b087f31c0e0056078dbf6d73a7f/ext/iobuffer/iobuffer.c#L104 line from cool.io gem, then Async HTTP server works.
Looks for me that async will change the behavior at https://github.com/socketry/async/blob/10fa816bb229d4df3433d337ded3421b43d161fe/lib/async/scheduler.rb#L253-L266 if cool.io is loaded.
Environment
- Windows 11
- Ruby 3.3.4
- async 2.16.1
- async-http 0.71.0
- cool.io 1.8.1
Reproduce code
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'async-http'
gem 'cool.io' # A problem is occurred if cool.io gem is loaded
end
require 'net/http'
require 'async/http/protocol'
require 'timeout'
module HttpServer
class Router
def initialize
@router = { get: {} }
end
def mount(method, path, app)
@router[method][path] = app
end
def route!(method, path, request)
@router.fetch(method).fetch(path).call(request)
end
end
class Server
class App
def initialize(router)
@router = router
end
def call(request)
method = request.method
resp = get(request)
Protocol::HTTP::Response[*resp]
rescue => e
Protocol::HTTP::Response[500, { 'Content-Type' => 'text/plain' }, 'Internal Server Error']
end
def get(request)
@router.route!(:get, request.path, request)
end
end
def initialize(addr:, port:, tls_context: nil)
@uri = URI("http://#{addr}:#{port}").to_s
@router = Router.new
@server_task = nil
@server = Async::HTTP::Server.new(App.new(@router), Async::HTTP::Endpoint.parse(@uri))
end
def start
Async do |task|
@server_task = task.async do
@server.run
end
end
end
def stop
@server_task&.stop
end
def get(path, app = nil, &block)
@router.mount(:get, path, app || block)
end
end
end
def http_server_start(addr:, port:)
server = HttpServer::Server.new(addr: addr, port: port)
server.get('/api/plugins.json') { |req| [200, { 'Content-Type' => 'text/html' }, "Hello"] }
Thread.new do
server.start
end
sleep 1 # Wait until the server starts up.
end
#################################################
puts "[http server start]"
http_server_start(addr: "127.0.0.1", port: "8080")
puts "-" * 80
puts "[client request]"
Timeout.timeout(10) {
p Net::HTTP.get(URI.parse("http://127.0.0.1:8080/api/plugins.json"))
}Result on Windows
C:\tmp> ruby .\async-http.rb
[http server start]
--------------------------------------------------------------------------------
[client request]
C:/Ruby33-x64/lib/ruby/3.3.0/timeout.rb:43:in `rescue in handle_timeout': execution expired (Timeout::Error)
from C:/Ruby33-x64/lib/ruby/3.3.0/timeout.rb:40:in `handle_timeout'
from C:/Ruby33-x64/lib/ruby/3.3.0/timeout.rb:195:in `timeout'
from ./async-http.rb:93:in `<main>'
C:/Ruby33-x64/lib/ruby/3.3.0/net/protocol.rb:229:in `wait_readable': execution expired (Timeout::ExitException)
from C:/Ruby33-x64/lib/ruby/3.3.0/net/protocol.rb:229:in `rbuf_fill'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/protocol.rb:199:in `readuntil'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/protocol.rb:209:in `readline'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http/response.rb:158:in `read_status_line'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http/response.rb:147:in `read_new'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http.rb:2342:in `block in transport_request'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http.rb:2333:in `catch'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http.rb:2333:in `transport_request'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http.rb:2306:in `request'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http.rb:2177:in `request_get'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http.rb:824:in `block in get_response'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http.rb:1570:in `start'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http.rb:1029:in `start'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http.rb:822:in `get_response'
from C:/Ruby33-x64/lib/ruby/3.3.0/net/http.rb:803:in `get'
from ./async-http.rb:94:in `block in <main>'
from C:/Ruby33-x64/lib/ruby/3.3.0/timeout.rb:186:in `block in timeout'
from C:/Ruby33-x64/lib/ruby/3.3.0/timeout.rb:41:in `handle_timeout'
from C:/Ruby33-x64/lib/ruby/3.3.0/timeout.rb:195:in `timeout'
from ./async-http.rb:93:in `<main>'
It got a timeout error because Async HTTP Server does not return any response.
Can you have any idea to solve this issue?