diff --git a/lib/async/io/shared_endpoint.rb b/lib/async/io/shared_endpoint.rb index 75018eb..c5dd76b 100644 --- a/lib/async/io/shared_endpoint.rb +++ b/lib/async/io/shared_endpoint.rb @@ -77,16 +77,9 @@ def bind task = Async::Task.current @wrappers.each do |server| - server = server.dup - task.async do |task| task.annotate "binding to #{server.inspect}" - - begin - yield server, task - ensure - server.close - end + yield server, task end end end @@ -109,9 +102,9 @@ def connect end end - def accept(backlog = nil, &block) + def accept(backlog = nil, **options, &block) bind do |server| - server.accept_each(&block) + server.accept_each(**options, &block) end end diff --git a/spec/async/io/shared_endpoint_spec.rb b/spec/async/io/shared_endpoint_spec.rb index c9d4316..1827c0f 100644 --- a/spec/async/io/shared_endpoint_spec.rb +++ b/spec/async/io/shared_endpoint_spec.rb @@ -10,7 +10,7 @@ include_context Async::RSpec::Reactor describe '#bound' do - let(:endpoint) {Async::IO::Endpoint.udp("localhost", 5123, timeout: 10)} + let(:endpoint) {Async::IO::Endpoint.tcp("localhost", 5123, timeout: 10)} it "can bind to shared endpoint" do bound_endpoint = described_class.bound(endpoint) @@ -33,6 +33,41 @@ bound_endpoint.close end + + it "can close a bound endpoint to terminate accept loop" do + bound_endpoint = described_class.bound(endpoint) + expect(bound_endpoint.wrappers).to_not be_empty + + server_task = Async do + bound_endpoint.accept do |io| + io.close + end + end + + connect = proc do + endpoint.connect do |io| + io.write "Hello World" + io.close + end + end + + connect.call + + wrapper = bound_endpoint.wrappers.first + expect(wrapper).to be_a Async::IO::Socket + + bound_endpoint.close + expect(wrapper).to be_closed + + expect do + begin + # Either ECONNRESET or ECONNREFUSED can be raised here. + connect.call + rescue Errno::ECONNRESET + raise Errno::ECONNREFUSED + end + end.to raise_error(Errno::ECONNREFUSED) + end end describe '#connected' do