From a4e953c655740bf46e45c3b6f488730489ce0901 Mon Sep 17 00:00:00 2001 From: Tim Carey-Smith Date: Tue, 21 May 2013 16:11:06 -0700 Subject: [PATCH 01/97] Allow waiting for read and write simultaneously Do not eagerly wait for IO-readiness --- lib/celluloid/io/reactor.rb | 97 ++++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 12 deletions(-) diff --git a/lib/celluloid/io/reactor.rb b/lib/celluloid/io/reactor.rb index 9e20f15..bb64337 100644 --- a/lib/celluloid/io/reactor.rb +++ b/lib/celluloid/io/reactor.rb @@ -14,20 +14,25 @@ class Reactor def initialize @selector = NIO::Selector.new + @monitors = {} end # Wait for the given IO object to become readable def wait_readable(io) - wait io, :r + wait io do |monitor| + monitor.wait_readable + end end # Wait for the given IO object to become writable def wait_writable(io) - wait io, :w + wait io do |monitor| + monitor.wait_writable + end end # Wait for the given IO operation to complete - def wait(io, set) + def wait(io) # zomg ugly type conversion :( unless io.is_a?(::IO) or io.is_a?(OpenSSL::SSL::SSLSocket) if io.respond_to? :to_io @@ -39,21 +44,89 @@ def wait(io, set) raise TypeError, "can't convert #{io.class} into IO" unless io.is_a?(::IO) end - monitor = @selector.register(io, set) - monitor.value = Task.current - Task.suspend :iowait + unless monitor = @monitors[io] + monitor = Monitor.new(@selector, io) + @monitors[io] = monitor + end + + yield monitor end # Run the reactor, waiting for events or wakeup signal def run_once(timeout = nil) @selector.select(timeout) do |monitor| - task = monitor.value - monitor.close + monitor.value.resume + end + end + + class Monitor + def initialize(selector, io) + @selector = selector + @io = io + @interests = {} + end + + def wait_readable + wait :r + end + + def wait_writable + wait :w + end + + def wait(interest) + raise "Already waiting for #{interest.inspect}" if @interests.include?(interest) + @interests[interest] = Task.current + reregister + Task.suspend :iowait + end + + def reregister + if @monitor + @monitor.close + @monitor = nil + end + + if interests_symbol + @monitor = @selector.register(@io, interests_symbol) + @monitor.value = self + end + end + + def interests_symbol + case @interests.keys + when [:r] + :r + when [:w] + :w + when [:r, :w] + :rw + end + end + + def resume + raise "No monitor" unless @monitor + + if @monitor.readable? + resume_for :r + end + + if @monitor.writable? + resume_for :w + end + + reregister + end + + def resume_for(interest) + task = @interests.delete(interest) - if task.running? - task.resume - else - Logger.warn("reactor attempted to resume a dead task") + if task + if task.running? + task.resume + else + raise "reactor attempted to resume a dead task" + end end end end From 6925df5a0b0ae22af2c5d35cd6b986cca3bc93d1 Mon Sep 17 00:00:00 2001 From: Tiago Cardoso Date: Tue, 4 Feb 2014 11:10:28 +0100 Subject: [PATCH 02/97] added spec for writing later to a socket within a request/response cycle using the timer primitives (this spec fails currently) --- spec/celluloid/io/tcp_server_spec.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index e7577bd..a8a1d9b 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -27,6 +27,31 @@ end end + it "sends information to the client later" do + class LaterActor < ExampleActor + def send_later(socket) + peer = socket.accept + after(0.4) { peer.write "1" } + after(0.4) { peer.write "2" } + peer + end + end + with_tcp_server do |subject| + thread = Thread.new { TCPSocket.new(example_addr, example_port) } + actor = LaterActor.new + begin + peer = actor.send_later(subject) + client = thread.value + client.write payload + peer.read(payload.size).should eq payload # confirm the client read + Timeout::timeout(1) { client.read(4).should eq "1" } + Timeout::timeout(2) { client.read(4).should eq "2" } + ensure + actor.terminate if actor.alive? + end + end + end + context "outside Celluloid::IO" do it "should be blocking" do with_tcp_server do |subject| From 7026e612f0cdc6086bea25e55b151816f751a9f2 Mon Sep 17 00:00:00 2001 From: Hendrik Beskow Date: Sat, 8 Mar 2014 18:51:04 +0100 Subject: [PATCH 03/97] expose connect method Signed-off-by: Hendrik Beskow --- lib/celluloid/io/udp_socket.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/celluloid/io/udp_socket.rb b/lib/celluloid/io/udp_socket.rb index bbb6140..f78ed9e 100644 --- a/lib/celluloid/io/udp_socket.rb +++ b/lib/celluloid/io/udp_socket.rb @@ -3,7 +3,7 @@ module IO # UDPSockets with combined blocking and evented support class UDPSocket extend Forwardable - def_delegators :@socket, :bind, :send, :recvfrom_nonblock, :close, :closed? + def_delegators :@socket, :bind, :connect, :send, :recvfrom_nonblock, :close, :closed? def initialize(address_family = ::Socket::AF_INET) @socket = ::UDPSocket.new(address_family) From f156afb1ec9a2d67ac06df23e96a30d2a63ab339 Mon Sep 17 00:00:00 2001 From: Hendrik Beskow Date: Wed, 23 Apr 2014 14:05:48 +0200 Subject: [PATCH 04/97] Add Windows and IPv6 DNSResolver support Also added random picking of DNS Servers, or is it recommended only to switch Namservers when one fails? --- lib/celluloid/io/dns_resolver.rb | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/celluloid/io/dns_resolver.rb b/lib/celluloid/io/dns_resolver.rb index 8c9fa43..33b87e8 100644 --- a/lib/celluloid/io/dns_resolver.rb +++ b/lib/celluloid/io/dns_resolver.rb @@ -1,11 +1,14 @@ +require 'ipaddr' require 'resolv' module Celluloid module IO # Asynchronous DNS resolver using Celluloid::IO::UDPSocket class DNSResolver - RESOLV_CONF = '/etc/resolv.conf' - DNS_PORT = 53 + # Maximum UDP packet we'll accept + MAX_PACKET_SIZE = 512 + RESOLV_CONF = '/etc/resolv.conf' + DNS_PORT = 53 @mutex = Mutex.new @identifier = 1 @@ -15,18 +18,17 @@ def self.generate_id end def self.nameservers(config = RESOLV_CONF) - File.read(config).scan(/^\s*nameserver\s+([0-9.:]+)/).flatten + Resolv::DNS::Config.default_config_hash(config)[:nameserver] end def initialize @nameservers = self.class.nameservers - # TODO: fall back on other nameservers if the first one is unavailable - @server = @nameservers.first + @server = IPAddr.new(@nameservers.sample) # The non-blocking secret sauce is here, as this is actually a # Celluloid::IO::UDPSocket - @socket = UDPSocket.new + @socket = UDPSocket.new(@server.family) end def resolve(hostname) @@ -38,8 +40,8 @@ def resolve(hostname) end query = build_query(hostname) - @socket.send query.encode, 0, @server, DNS_PORT - data, _ = @socket.recvfrom(512) + @socket.send query.encode, 0, @server.to_s, DNS_PORT + data, _ = @socket.recvfrom(MAX_PACKET_SIZE) response = Resolv::DNS::Message.decode(data) addrs = [] From b90c3a64ec44ffc2a3f0f68ec0d47475110c44cd Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 5 May 2014 01:03:54 -0700 Subject: [PATCH 05/97] Add Celluloid::IO::TCPSocket#getsockname --- lib/celluloid/io/tcp_socket.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/celluloid/io/tcp_socket.rb b/lib/celluloid/io/tcp_socket.rb index a348fdc..eebcad3 100644 --- a/lib/celluloid/io/tcp_socket.rb +++ b/lib/celluloid/io/tcp_socket.rb @@ -8,7 +8,7 @@ class TCPSocket < Stream extend Forwardable def_delegators :@socket, :read_nonblock, :write_nonblock, :close, :close_read, :close_write, :closed? - def_delegators :@socket, :addr, :peeraddr, :setsockopt + def_delegators :@socket, :addr, :peeraddr, :setsockopt, :getsockname # Open a TCP socket, yielding it to the given block and closing it # automatically when done (if a block is given) From 9a99328a9d0435f8fbb209c93c31771b634c06b4 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 5 May 2014 01:05:44 -0700 Subject: [PATCH 06/97] Bump Travis Ruby version to 2.1.1 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ede7c55..621f68d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ script: rake ci rvm: - 1.9.3 - 2.0.0 - - 2.1.0 + - 2.1.1 - ruby-head - jruby - jruby-head From cef0f8364bc9eb23d8cd37f07f24755514fe6419 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 5 May 2014 01:06:12 -0700 Subject: [PATCH 07/97] Update .rspec --- .rspec | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.rspec b/.rspec index 270de17..57badd3 100644 --- a/.rspec +++ b/.rspec @@ -1,4 +1,5 @@ ---color ---format documentation +--color +--format documentation --backtrace ---default_path spec +--order random +--warnings From aa4a7c3ef3bffc739788fee13324fd3645fb0804 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 5 May 2014 01:24:40 -0700 Subject: [PATCH 08/97] Obtain resolv hosts via Resolv::Hosts::DefaultFileName --- lib/celluloid/io/dns_resolver.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/celluloid/io/dns_resolver.rb b/lib/celluloid/io/dns_resolver.rb index 33b87e8..af0e3bb 100644 --- a/lib/celluloid/io/dns_resolver.rb +++ b/lib/celluloid/io/dns_resolver.rb @@ -7,7 +7,6 @@ module IO class DNSResolver # Maximum UDP packet we'll accept MAX_PACKET_SIZE = 512 - RESOLV_CONF = '/etc/resolv.conf' DNS_PORT = 53 @mutex = Mutex.new @@ -17,7 +16,7 @@ def self.generate_id @mutex.synchronize { @identifier = (@identifier + 1) & 0xFFFF } end - def self.nameservers(config = RESOLV_CONF) + def self.nameservers(config = Resolv::Hosts::DefaultFileName) Resolv::DNS::Config.default_config_hash(config)[:nameserver] end From 07edffe57bc9f100d33cdd8044ea5d3fa04cd736 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 12 May 2014 19:29:32 -0700 Subject: [PATCH 09/97] Revert "Obtain resolv hosts via Resolv::Hosts::DefaultFileName" This reverts commit aa4a7c3ef3bffc739788fee13324fd3645fb0804. Ungh, resolv.conf vs hosts --- lib/celluloid/io/dns_resolver.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/celluloid/io/dns_resolver.rb b/lib/celluloid/io/dns_resolver.rb index af0e3bb..33b87e8 100644 --- a/lib/celluloid/io/dns_resolver.rb +++ b/lib/celluloid/io/dns_resolver.rb @@ -7,6 +7,7 @@ module IO class DNSResolver # Maximum UDP packet we'll accept MAX_PACKET_SIZE = 512 + RESOLV_CONF = '/etc/resolv.conf' DNS_PORT = 53 @mutex = Mutex.new @@ -16,7 +17,7 @@ def self.generate_id @mutex.synchronize { @identifier = (@identifier + 1) & 0xFFFF } end - def self.nameservers(config = Resolv::Hosts::DefaultFileName) + def self.nameservers(config = RESOLV_CONF) Resolv::DNS::Config.default_config_hash(config)[:nameserver] end From a72cae2ee0379c4eff2898aca8b9a20377a74fe9 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 12 May 2014 19:32:17 -0700 Subject: [PATCH 10/97] Let Resolv::DNS::Config.default_config_hash do its thing --- lib/celluloid/io/dns_resolver.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/celluloid/io/dns_resolver.rb b/lib/celluloid/io/dns_resolver.rb index 33b87e8..d0001dd 100644 --- a/lib/celluloid/io/dns_resolver.rb +++ b/lib/celluloid/io/dns_resolver.rb @@ -7,7 +7,6 @@ module IO class DNSResolver # Maximum UDP packet we'll accept MAX_PACKET_SIZE = 512 - RESOLV_CONF = '/etc/resolv.conf' DNS_PORT = 53 @mutex = Mutex.new @@ -17,8 +16,8 @@ def self.generate_id @mutex.synchronize { @identifier = (@identifier + 1) & 0xFFFF } end - def self.nameservers(config = RESOLV_CONF) - Resolv::DNS::Config.default_config_hash(config)[:nameserver] + def self.nameservers + Resolv::DNS::Config.default_config_hash[:nameserver] end def initialize From ed6dbe189e50e4df85705a397207b708fef78669 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 12 May 2014 19:34:39 -0700 Subject: [PATCH 11/97] Use rbx-2 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 621f68d..d98876b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,14 +6,14 @@ rvm: - ruby-head - jruby - jruby-head - - rbx + - rbx-2 matrix: allow_failures: - rvm: ruby-head - rvm: jruby - rvm: jruby-head - - rvm: rbx + - rvm: rbx-2 notifications: irc: "irc.freenode.org#celluloid" From 3db545d08207ee96a6d99e1a82f7d9d1f296224a Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 22 Jun 2014 18:55:10 -0700 Subject: [PATCH 12/97] CHANGES + version bump to 0.16.0.pre2 --- CHANGES.md | 6 ++++-- lib/celluloid/io/version.rb | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 618aa8a..ff5e54f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,7 @@ -HEAD ----- +0.16.0.pre2 (2014-06-22) +------------------------ +* Fix bug handling simultaneous read/write interests +* Use Resolv::DNS::Config to obtain nameservers * Celluloid::IO.copy_stream support (uses a background thread) 0.15.0 (2013-09-04) diff --git a/lib/celluloid/io/version.rb b/lib/celluloid/io/version.rb index d2d25cc..5aa80fc 100644 --- a/lib/celluloid/io/version.rb +++ b/lib/celluloid/io/version.rb @@ -1,5 +1,5 @@ module Celluloid module IO - VERSION = "0.16.0.pre" + VERSION = "0.16.0.pre2" end end From 288917a56f6e5be9fbc62fc534c7927bcf9be0d2 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 4 Sep 2014 19:56:49 -0700 Subject: [PATCH 13/97] Bump version to 0.16.0 --- CHANGES.md | 4 ++-- celluloid-io.gemspec | 2 +- lib/celluloid/io/version.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ff5e54f..0aaf9eb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,5 @@ -0.16.0.pre2 (2014-06-22) ------------------------- +0.16.0 (2014-09-04) +------------------- * Fix bug handling simultaneous read/write interests * Use Resolv::DNS::Config to obtain nameservers * Celluloid::IO.copy_stream support (uses a background thread) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index 5adc103..1b15f4a 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |gem| gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") gem.require_paths = ["lib"] - gem.add_dependency 'celluloid', '>= 0.16.0.pre' + gem.add_dependency 'celluloid', '>= 0.16.0' gem.add_dependency 'nio4r', '>= 1.0.0' gem.add_development_dependency 'rake' diff --git a/lib/celluloid/io/version.rb b/lib/celluloid/io/version.rb index 5aa80fc..eaacdd2 100644 --- a/lib/celluloid/io/version.rb +++ b/lib/celluloid/io/version.rb @@ -1,5 +1,5 @@ module Celluloid module IO - VERSION = "0.16.0.pre2" + VERSION = "0.16.0" end end From 879439e73c36d67a4413ad22b3d4591c6fbab930 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 4 Sep 2014 20:43:01 -0700 Subject: [PATCH 14/97] Lock to RSpec ~> 2.14 --- celluloid-io.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index 1b15f4a..92178d8 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |gem| gem.add_dependency 'nio4r', '>= 1.0.0' gem.add_development_dependency 'rake' - gem.add_development_dependency 'rspec' + gem.add_development_dependency 'rspec', '~> 2.14.0' gem.add_development_dependency 'benchmark_suite' gem.add_development_dependency 'guard-rspec' gem.add_development_dependency 'rb-fsevent', '~> 0.9.1' if RUBY_PLATFORM =~ /darwin/ From 0485997b1c1f1ff412c7f6317333bafb499313a3 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 4 Sep 2014 20:47:44 -0700 Subject: [PATCH 15/97] Fix TCPServer creation without a hostname --- lib/celluloid/io/tcp_server.rb | 6 +++++- spec/celluloid/io/tcp_server_spec.rb | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/celluloid/io/tcp_server.rb b/lib/celluloid/io/tcp_server.rb index 307acf4..40ca5b3 100644 --- a/lib/celluloid/io/tcp_server.rb +++ b/lib/celluloid/io/tcp_server.rb @@ -8,7 +8,11 @@ class TCPServer def_delegators :@server, :listen, :sysaccept, :close, :closed?, :addr, :setsockopt def initialize(hostname_or_port, port = nil) - @server = ::TCPServer.new(hostname_or_port, port) + if port.nil? + @server = ::TCPServer.new(hostname_or_port) + else + @server = ::TCPServer.new(hostname_or_port, port) + end end def accept diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index e7577bd..bfb3437 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -5,7 +5,7 @@ let(:payload) { 'ohai' } it "can be initialized without a host" do - expect{ server = Celluloid::IO::TCPServer.new(2000); server.close }.to_not raise_error + expect { Celluloid::IO::TCPServer.new(2000).close }.to_not raise_error end context "inside Celluloid::IO" do From bd7beee7e0b5872392927102e922e47b796565cb Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 8 Sep 2014 10:03:49 -0700 Subject: [PATCH 16/97] Return Celluloid::IO::SSLSocket after connect --- lib/celluloid/io/ssl_socket.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/celluloid/io/ssl_socket.rb b/lib/celluloid/io/ssl_socket.rb index dce281c..5f5ab46 100644 --- a/lib/celluloid/io/ssl_socket.rb +++ b/lib/celluloid/io/ssl_socket.rb @@ -17,6 +17,7 @@ def initialize(io, ctx = OpenSSL::SSL::SSLContext.new) def connect @socket.connect_nonblock + self rescue ::IO::WaitReadable wait_readable retry From 9ccce9ba40535b4fa204e69f312bc2fe53dda3a1 Mon Sep 17 00:00:00 2001 From: henning mueller Date: Tue, 23 Sep 2014 11:31:05 +0200 Subject: [PATCH 17/97] Expose addr method. --- lib/celluloid/io/udp_socket.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/celluloid/io/udp_socket.rb b/lib/celluloid/io/udp_socket.rb index f78ed9e..290655e 100644 --- a/lib/celluloid/io/udp_socket.rb +++ b/lib/celluloid/io/udp_socket.rb @@ -3,7 +3,7 @@ module IO # UDPSockets with combined blocking and evented support class UDPSocket extend Forwardable - def_delegators :@socket, :bind, :connect, :send, :recvfrom_nonblock, :close, :closed? + def_delegators :@socket, :addr, :bind, :connect, :send, :recvfrom_nonblock, :close, :closed? def initialize(address_family = ::Socket::AF_INET) @socket = ::UDPSocket.new(address_family) From d0662b981a3ca66a4ea4cabd66ef42a112f3420c Mon Sep 17 00:00:00 2001 From: Patrik Wenger Date: Tue, 30 Sep 2014 04:39:10 +0200 Subject: [PATCH 18/97] DNSResolver: fix crash when networking is disabled and not needed This commit fixes the issue when "localhost" is tried to be resolved where it used to fail when networking on Mac OSX is disabled. When it's disabled, the file /etc/resolv.conf doesn't exist and thus the method Celluloid::IO::DNSResolver.nameservers returns nil, which shouldn't be a problem because networking isn't really needed to resolve "localhost". It can use static lookup with /etc/hosts. --- lib/celluloid/io/dns_resolver.rb | 17 +++++++---------- spec/celluloid/io/dns_resolver_spec.rb | 8 ++++++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/celluloid/io/dns_resolver.rb b/lib/celluloid/io/dns_resolver.rb index d0001dd..ba8a26d 100644 --- a/lib/celluloid/io/dns_resolver.rb +++ b/lib/celluloid/io/dns_resolver.rb @@ -20,16 +20,6 @@ def self.nameservers Resolv::DNS::Config.default_config_hash[:nameserver] end - def initialize - @nameservers = self.class.nameservers - - @server = IPAddr.new(@nameservers.sample) - - # The non-blocking secret sauce is here, as this is actually a - # Celluloid::IO::UDPSocket - @socket = UDPSocket.new(@server.family) - end - def resolve(hostname) if host = resolve_hostname(hostname) unless ip_address = resolve_host(host) @@ -38,6 +28,13 @@ def resolve(hostname) return ip_address end + @nameservers = self.class.nameservers + @server = IPAddr.new(@nameservers.sample) + + # The non-blocking secret sauce is here, as this is actually a + # Celluloid::IO::UDPSocket + @socket = UDPSocket.new(@server.family) + query = build_query(hostname) @socket.send query.encode, 0, @server.to_s, DNS_PORT data, _ = @socket.recvfrom(MAX_PACKET_SIZE) diff --git a/spec/celluloid/io/dns_resolver_spec.rb b/spec/celluloid/io/dns_resolver_spec.rb index 036ab1d..d259828 100644 --- a/spec/celluloid/io/dns_resolver_spec.rb +++ b/spec/celluloid/io/dns_resolver_spec.rb @@ -2,6 +2,14 @@ describe Celluloid::IO::DNSResolver do describe '#resolve' do + it 'resolves hostnames statically from hosts file without nameservers' do + # /etc/resolv.conf doesn't exist on Mac OSX when no networking is + # disabled, thus .nameservers would return nil + Celluloid::IO::DNSResolver.should_receive(:nameservers).at_most(:once) { nil } + resolver = Celluloid::IO::DNSResolver.new + resolver.resolve('localhost').should eq Resolv::IPv4.create("127.0.0.1") + end + it 'resolves hostnames' do resolver = Celluloid::IO::DNSResolver.new resolver.resolve('localhost').should eq Resolv::IPv4.create("127.0.0.1") From 3a899049af3ce554b714a1f8430e4ae55b8b1f65 Mon Sep 17 00:00:00 2001 From: Patrik Wenger Date: Wed, 1 Oct 2014 03:10:21 +0200 Subject: [PATCH 19/97] restore caching and old complexity of #resolve --- lib/celluloid/io/dns_resolver.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/celluloid/io/dns_resolver.rb b/lib/celluloid/io/dns_resolver.rb index ba8a26d..be0ef5e 100644 --- a/lib/celluloid/io/dns_resolver.rb +++ b/lib/celluloid/io/dns_resolver.rb @@ -20,6 +20,18 @@ def self.nameservers Resolv::DNS::Config.default_config_hash[:nameserver] end + def initialize + # early return for edge case when there are no nameservers configured + # but we still want to be able to static lookups using #resolve_hostname + @nameservers = self.class.nameservers or return + + @server = IPAddr.new(@nameservers.sample) + + # The non-blocking secret sauce is here, as this is actually a + # Celluloid::IO::UDPSocket + @socket = UDPSocket.new(@server.family) + end + def resolve(hostname) if host = resolve_hostname(hostname) unless ip_address = resolve_host(host) @@ -28,13 +40,6 @@ def resolve(hostname) return ip_address end - @nameservers = self.class.nameservers - @server = IPAddr.new(@nameservers.sample) - - # The non-blocking secret sauce is here, as this is actually a - # Celluloid::IO::UDPSocket - @socket = UDPSocket.new(@server.family) - query = build_query(hostname) @socket.send query.encode, 0, @server.to_s, DNS_PORT data, _ = @socket.recvfrom(MAX_PACKET_SIZE) From 9f92899f03a32dfd04beaccfe35439a7443c20a7 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 7 Oct 2014 22:26:28 -0700 Subject: [PATCH 20/97] CloudFlare yo! --- spec/celluloid/io/.dns_resolver_spec.rb.swp | Bin 0 -> 12288 bytes spec/celluloid/io/dns_resolver_spec.rb | 6 ++++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 spec/celluloid/io/.dns_resolver_spec.rb.swp diff --git a/spec/celluloid/io/.dns_resolver_spec.rb.swp b/spec/celluloid/io/.dns_resolver_spec.rb.swp new file mode 100644 index 0000000000000000000000000000000000000000..a3b6851ae481b82733f7522b2578d2cd55c98911 GIT binary patch literal 12288 zcmeI2zmFS56vyXI0zu#cBLBdPUDy_6ZQq@g$Ph(QKqAE@=mH2xVXb$c&m+b=&dm5W zrv&JbDEKGn5Cu|bpo9_{YKjyz2qgXk3ckDEb$oD_AEH2s-df+?_3q4@H=j52B+GBq zd-w7VosG5>ju(~s^T+MCe`z(>UOlbUDE7(RaPj88hYv13FnVtiqET!NyJK2^Tp8?o zmvj?0W^Sxb&uH8AGhTVp#gjDiL&x5leRjj*b>v3Jn3cyuKnOgDz&wo4oZC=aoBdwV zwAnaKr(SyJLA~U?5D)@FKnMr{As_^VfDjM@PY{7HTT`E4KI_$-Uaqcd|F~9P4bS~UQjFB+9Ko>6tvZsd6$9mErBqr^@d zb&n=_o$VRM+=Dxas!^JBs5Rx<7)-dfnv#pN)K1L-C%;pJ8u+NW;XNe8t4X_JAv`)MEVEc=RE~TUrrP>)p|^}pVl%Nmv^w?f;v2{C z+B_Te@ag~C*@yMCRXO0P7_xM;bwo7(S2yW?>vORuQ52rA-skpUCB~g74#O#?)gD;n zxDMT-Oq*pcYEr6wJTjcVLSZuZ6s`27yv&l0!`vZ!+LX(is7YN8Nq4~m+bJ7^7W=Ff zh;M2i$Y!(?Cv^4Ndqr|VS4$a(+`12us7U+L4mQ&f;0d`nXha{0Y3%H@42h?)MqbKw xK;90Eg|ygDWt@mo_KDNTZmnh&rSiq{@$q}RjI-k#bM4T(sHPuI*v#0q)Zg&6O=bW9 literal 0 HcmV?d00001 diff --git a/spec/celluloid/io/dns_resolver_spec.rb b/spec/celluloid/io/dns_resolver_spec.rb index d259828..87ca2c7 100644 --- a/spec/celluloid/io/dns_resolver_spec.rb +++ b/spec/celluloid/io/dns_resolver_spec.rb @@ -16,8 +16,10 @@ end it "resolves domain names" do - resolver = Celluloid::IO::DNSResolver.new - resolver.resolve("celluloid.io").should == Resolv::IPv4.create("207.97.227.245") + resolver = Celluloid::IO::DNSResolver.new + nameservers = resolver.resolve("celluloid.io") + expect(nameservers).to include Resolv::IPv4.create("104.28.21.100") + expect(nameservers).to include Resolv::IPv4.create("104.28.20.100") end it "resolves CNAME responses" do From f01563676333cae92e30384559c09163a37a8913 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 7 Oct 2014 22:08:12 -0700 Subject: [PATCH 21/97] Revert "Allow waiting for read and write simultaneously" This reverts commit a4e953c655740bf46e45c3b6f488730489ce0901. --- lib/celluloid/io/reactor.rb | 97 +++++-------------------------------- 1 file changed, 12 insertions(+), 85 deletions(-) diff --git a/lib/celluloid/io/reactor.rb b/lib/celluloid/io/reactor.rb index bb64337..9e20f15 100644 --- a/lib/celluloid/io/reactor.rb +++ b/lib/celluloid/io/reactor.rb @@ -14,25 +14,20 @@ class Reactor def initialize @selector = NIO::Selector.new - @monitors = {} end # Wait for the given IO object to become readable def wait_readable(io) - wait io do |monitor| - monitor.wait_readable - end + wait io, :r end # Wait for the given IO object to become writable def wait_writable(io) - wait io do |monitor| - monitor.wait_writable - end + wait io, :w end # Wait for the given IO operation to complete - def wait(io) + def wait(io, set) # zomg ugly type conversion :( unless io.is_a?(::IO) or io.is_a?(OpenSSL::SSL::SSLSocket) if io.respond_to? :to_io @@ -44,89 +39,21 @@ def wait(io) raise TypeError, "can't convert #{io.class} into IO" unless io.is_a?(::IO) end - unless monitor = @monitors[io] - monitor = Monitor.new(@selector, io) - @monitors[io] = monitor - end - - yield monitor + monitor = @selector.register(io, set) + monitor.value = Task.current + Task.suspend :iowait end # Run the reactor, waiting for events or wakeup signal def run_once(timeout = nil) @selector.select(timeout) do |monitor| - monitor.value.resume - end - end - - class Monitor - def initialize(selector, io) - @selector = selector - @io = io - @interests = {} - end - - def wait_readable - wait :r - end - - def wait_writable - wait :w - end - - def wait(interest) - raise "Already waiting for #{interest.inspect}" if @interests.include?(interest) - @interests[interest] = Task.current - reregister - Task.suspend :iowait - end - - def reregister - if @monitor - @monitor.close - @monitor = nil - end - - if interests_symbol - @monitor = @selector.register(@io, interests_symbol) - @monitor.value = self - end - end - - def interests_symbol - case @interests.keys - when [:r] - :r - when [:w] - :w - when [:r, :w] - :rw - end - end - - def resume - raise "No monitor" unless @monitor - - if @monitor.readable? - resume_for :r - end - - if @monitor.writable? - resume_for :w - end - - reregister - end - - def resume_for(interest) - task = @interests.delete(interest) + task = monitor.value + monitor.close - if task - if task.running? - task.resume - else - raise "reactor attempted to resume a dead task" - end + if task.running? + task.resume + else + Logger.warn("reactor attempted to resume a dead task") end end end From 1b79f698c850339cc63c37c65f6698ea1603e24d Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 8 Oct 2014 10:06:53 -0700 Subject: [PATCH 22/97] Bump version to 0.16.1 and note changes --- CHANGES.md | 4 ++++ lib/celluloid/io/version.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 0aaf9eb..e5f701c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,7 @@ +0.16.1 (2014-10-08) +------------------- +* Revert read/write interest patch as it caused file descriptor leaks + 0.16.0 (2014-09-04) ------------------- * Fix bug handling simultaneous read/write interests diff --git a/lib/celluloid/io/version.rb b/lib/celluloid/io/version.rb index eaacdd2..f95e6bf 100644 --- a/lib/celluloid/io/version.rb +++ b/lib/celluloid/io/version.rb @@ -1,5 +1,5 @@ module Celluloid module IO - VERSION = "0.16.0" + VERSION = "0.16.1" end end From 93fd9856f01c05c43fb0c7c24784ab6b94ef785e Mon Sep 17 00:00:00 2001 From: stopiccot Date: Tue, 18 Nov 2014 18:16:02 +0300 Subject: [PATCH 23/97] Fixed invalid Errno::EAGAIN handling in Stream#syswrite --- lib/celluloid/io/stream.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/celluloid/io/stream.rb b/lib/celluloid/io/stream.rb index 19f50ce..8817974 100644 --- a/lib/celluloid/io/stream.rb +++ b/lib/celluloid/io/stream.rb @@ -64,6 +64,9 @@ def syswrite(string) retry rescue EOFError return total_written + rescue Errno::EAGAIN + wait_writable + retry end total_written += written From cf01674072fe420770ed27af92ea7f95f7579503 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Fri, 5 Dec 2014 22:02:45 +1300 Subject: [PATCH 24/97] Delete .dns_resolver_spec.rb.swp Did you really mean to commit this file? --- spec/celluloid/io/.dns_resolver_spec.rb.swp | Bin 12288 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 spec/celluloid/io/.dns_resolver_spec.rb.swp diff --git a/spec/celluloid/io/.dns_resolver_spec.rb.swp b/spec/celluloid/io/.dns_resolver_spec.rb.swp deleted file mode 100644 index a3b6851ae481b82733f7522b2578d2cd55c98911..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2zmFS56vyXI0zu#cBLBdPUDy_6ZQq@g$Ph(QKqAE@=mH2xVXb$c&m+b=&dm5W zrv&JbDEKGn5Cu|bpo9_{YKjyz2qgXk3ckDEb$oD_AEH2s-df+?_3q4@H=j52B+GBq zd-w7VosG5>ju(~s^T+MCe`z(>UOlbUDE7(RaPj88hYv13FnVtiqET!NyJK2^Tp8?o zmvj?0W^Sxb&uH8AGhTVp#gjDiL&x5leRjj*b>v3Jn3cyuKnOgDz&wo4oZC=aoBdwV zwAnaKr(SyJLA~U?5D)@FKnMr{As_^VfDjM@PY{7HTT`E4KI_$-Uaqcd|F~9P4bS~UQjFB+9Ko>6tvZsd6$9mErBqr^@d zb&n=_o$VRM+=Dxas!^JBs5Rx<7)-dfnv#pN)K1L-C%;pJ8u+NW;XNe8t4X_JAv`)MEVEc=RE~TUrrP>)p|^}pVl%Nmv^w?f;v2{C z+B_Te@ag~C*@yMCRXO0P7_xM;bwo7(S2yW?>vORuQ52rA-skpUCB~g74#O#?)gD;n zxDMT-Oq*pcYEr6wJTjcVLSZuZ6s`27yv&l0!`vZ!+LX(is7YN8Nq4~m+bJ7^7W=Ff zh;M2i$Y!(?Cv^4Ndqr|VS4$a(+`12us7U+L4mQ&f;0d`nXha{0Y3%H@42h?)MqbKw xK;90Eg|ygDWt@mo_KDNTZmnh&rSiq{@$q}RjI-k#bM4T(sHPuI*v#0q)Zg&6O=bW9 From d65598f46c04975cf2ec55b125eadc3af73e3a17 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Fri, 5 Dec 2014 21:41:32 +1300 Subject: [PATCH 25/97] Add failing spec based on Tiago's example actor. --- spec/celluloid/io/reactor_spec.rb | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 spec/celluloid/io/reactor_spec.rb diff --git a/spec/celluloid/io/reactor_spec.rb b/spec/celluloid/io/reactor_spec.rb new file mode 100644 index 0000000..9c63990 --- /dev/null +++ b/spec/celluloid/io/reactor_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Celluloid::IO::Reactor do + let(:payload) { "balls" } + + it "shouldn't crash" do + server = ::TCPServer.new example_addr, example_port + + thread = Thread.new { server.accept } + + socket = within_io_actor { Celluloid::IO::TCPSocket.new example_addr, example_port } + peer = thread.value + peer_thread = Thread.new { loop { peer << payload } } + handle = false + + # Main server body: + within_io_actor do + begin + timeout(2) do + loop do + socket.readpartial(2046) + end + end + # rescuing timeout, ok. rescuing terminated error, is it ok? TODO: investigate + rescue Celluloid::Task::TerminatedError, Timeout::Error + ensure + socket.readpartial(2046) + handle = true + end + end + + expect(handle).to be_true + + server.close + peer.close + socket.close + end +end From 722e0de865c546c4a5432f798e061ff1cc594799 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 29 Oct 2014 11:28:12 +1300 Subject: [PATCH 26/97] Ensure monitor is closed after task is resumed. --- lib/celluloid/io/reactor.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/celluloid/io/reactor.rb b/lib/celluloid/io/reactor.rb index 9e20f15..9304eb4 100644 --- a/lib/celluloid/io/reactor.rb +++ b/lib/celluloid/io/reactor.rb @@ -41,14 +41,22 @@ def wait(io, set) monitor = @selector.register(io, set) monitor.value = Task.current - Task.suspend :iowait + + begin + Task.suspend :iowait + ensure + # In all cases we want to ensure that the monitor is closed once we + # have woken up. However, in some cases, the monitor is already + # invalid, e.g. in the case that we are terminating. We catch this + # case explicitly. + monitor.close unless Celluloid::Task::TerminatedError === $! + end end # Run the reactor, waiting for events or wakeup signal def run_once(timeout = nil) @selector.select(timeout) do |monitor| task = monitor.value - monitor.close if task.running? task.resume From bbb0d06e4e114644a3156e4a76f05cf8515890df Mon Sep 17 00:00:00 2001 From: Tiago Cardoso Date: Sun, 4 Jan 2015 03:53:16 +0100 Subject: [PATCH 27/97] removing exception check from monitor close --- lib/celluloid/io/reactor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/celluloid/io/reactor.rb b/lib/celluloid/io/reactor.rb index 9304eb4..22da5e8 100644 --- a/lib/celluloid/io/reactor.rb +++ b/lib/celluloid/io/reactor.rb @@ -49,7 +49,7 @@ def wait(io, set) # have woken up. However, in some cases, the monitor is already # invalid, e.g. in the case that we are terminating. We catch this # case explicitly. - monitor.close unless Celluloid::Task::TerminatedError === $! + monitor.close end end From ed5102c1ebba2dd76293ed864b2f3f1f1de6eab4 Mon Sep 17 00:00:00 2001 From: Tiago Cardoso Date: Sat, 17 Jan 2015 01:14:00 +0100 Subject: [PATCH 28/97] corrected return value semantics for celluloid io tcpsocket (now compatible with native tcpsocket) ( This fixes celluloid/celluloid-io#124 ) --- lib/celluloid/io/tcp_socket.rb | 2 +- spec/celluloid/io/tcp_socket_spec.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/celluloid/io/tcp_socket.rb b/lib/celluloid/io/tcp_socket.rb index eebcad3..e6ec8f2 100644 --- a/lib/celluloid/io/tcp_socket.rb +++ b/lib/celluloid/io/tcp_socket.rb @@ -17,7 +17,7 @@ def self.open(*args, &block) if block_given? begin - yield sock + return yield(sock) ensure sock.close end diff --git a/spec/celluloid/io/tcp_socket_spec.rb b/spec/celluloid/io/tcp_socket_spec.rb index 82f84e1..e2e9ddf 100644 --- a/spec/celluloid/io/tcp_socket_spec.rb +++ b/spec/celluloid/io/tcp_socket_spec.rb @@ -4,6 +4,33 @@ let(:payload) { 'ohai' } context "inside Celluloid::IO" do + + describe ".open" do + it "returns the open socket" do + server = ::TCPServer.new example_addr, example_port + thread = Thread.new { server.accept } + + socket = within_io_actor { Celluloid::IO::TCPSocket.open(example_addr, example_port) } + socket.should be_a(Celluloid::IO::TCPSocket) + + server.close + thread.terminate + socket.close + end + context "when passed a block" do + it "returns the block evaluation" do + server = ::TCPServer.new example_addr, example_port + thread = Thread.new { server.accept } + + value = within_io_actor { Celluloid::IO::TCPSocket.open(example_addr, example_port) { true } } + value.should be_true + + server.close + thread.terminate + end + end + end + it "connects to TCP servers" do server = ::TCPServer.new example_addr, example_port thread = Thread.new { server.accept } From 5009f84c8d05e3a5e2f3ce6e87638fcfe3ab9501 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 19 Jan 2015 13:45:17 -0800 Subject: [PATCH 29/97] Tighten up Celluloid::IO::TCPSocket.open --- lib/celluloid/io/tcp_socket.rb | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/celluloid/io/tcp_socket.rb b/lib/celluloid/io/tcp_socket.rb index e6ec8f2..f6d0bed 100644 --- a/lib/celluloid/io/tcp_socket.rb +++ b/lib/celluloid/io/tcp_socket.rb @@ -14,16 +14,13 @@ class TCPSocket < Stream # automatically when done (if a block is given) def self.open(*args, &block) sock = new(*args) + return sock unless block_given? - if block_given? - begin - return yield(sock) - ensure - sock.close - end + begin + yield(sock) + ensure + sock.close end - - sock end # Convert a Ruby TCPSocket into a Celluloid::IO::TCPSocket From a70afaa4fd4af8ae4d15679df8e5a4418ef84183 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 30 Jan 2015 09:52:53 -0800 Subject: [PATCH 30/97] Bump nio4r dependency --- celluloid-io.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index 92178d8..e2cdc78 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |gem| gem.require_paths = ["lib"] gem.add_dependency 'celluloid', '>= 0.16.0' - gem.add_dependency 'nio4r', '>= 1.0.0' + gem.add_dependency 'nio4r', '>= 1.1.0' gem.add_development_dependency 'rake' gem.add_development_dependency 'rspec', '~> 2.14.0' From 0323e037ea10c3632daaf4857a6209ed72975c77 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 30 Jan 2015 09:54:40 -0800 Subject: [PATCH 31/97] Bump version to 0.16.2 and note CHANGES --- CHANGES.md | 6 ++++++ lib/celluloid/io/version.rb | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index e5f701c..7e05416 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +0.16.2 (2014-01-30) +------------------- +* More TCPSocket compatibility fixes +* Ensure monitors are closed when tasks resume +* Fix Errno::EAGAIN handling in Stream#syswrite + 0.16.1 (2014-10-08) ------------------- * Revert read/write interest patch as it caused file descriptor leaks diff --git a/lib/celluloid/io/version.rb b/lib/celluloid/io/version.rb index f95e6bf..90c6efe 100644 --- a/lib/celluloid/io/version.rb +++ b/lib/celluloid/io/version.rb @@ -1,5 +1,5 @@ module Celluloid module IO - VERSION = "0.16.1" + VERSION = "0.16.2" end end From b25a0bbf4e979404a1ab062c5c53ae6f4dc8e90b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoffer=20Lerv=C3=A5g?= Date: Tue, 3 Feb 2015 13:00:04 +0100 Subject: [PATCH 32/97] Fix typo --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 7e05416..17ecd88 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,4 @@ -0.16.2 (2014-01-30) +0.16.2 (2015-01-30) ------------------- * More TCPSocket compatibility fixes * Ensure monitors are closed when tasks resume From c006b215620dc8136fce0a52d8fdcb88947fe3fe Mon Sep 17 00:00:00 2001 From: Zach Anker Date: Mon, 6 Apr 2015 10:34:15 -0700 Subject: [PATCH 33/97] Avoid SSLSocket leaks by setting sync_close by default and allow overriding --- lib/celluloid/io/ssl_socket.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/celluloid/io/ssl_socket.rb b/lib/celluloid/io/ssl_socket.rb index 5f5ab46..b860a61 100644 --- a/lib/celluloid/io/ssl_socket.rb +++ b/lib/celluloid/io/ssl_socket.rb @@ -7,12 +7,13 @@ class SSLSocket < Stream extend Forwardable def_delegators :@socket, :read_nonblock, :write_nonblock, :close, :closed?, - :cert, :cipher, :client_ca, :peer_cert, :peer_cert_chain, :verify_result, :peeraddr + :cert, :cipher, :client_ca, :peer_cert, :peer_cert_chain, :verify_result, :peeraddr, :sync_close= def initialize(io, ctx = OpenSSL::SSL::SSLContext.new) super() @context = ctx @socket = OpenSSL::SSL::SSLSocket.new(::IO.try_convert(io), @context) + @socket.sync_close = true if @socket.respond_to?(:sync_close=) end def connect From 113f52dc10457d1c4924ccb6c3ede695408ae52f Mon Sep 17 00:00:00 2001 From: //de Date: Mon, 6 Apr 2015 13:41:17 -0700 Subject: [PATCH 34/97] anticipate 0.17.0 in this branch --- celluloid-io.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index e2cdc78..55f551a 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |gem| gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") gem.require_paths = ["lib"] - gem.add_dependency 'celluloid', '>= 0.16.0' + gem.add_dependency 'celluloid', '>= 0.17.0' gem.add_dependency 'nio4r', '>= 1.1.0' gem.add_development_dependency 'rake' From b10c45f0b9a73cc9910c19fee3770649d713ba6c Mon Sep 17 00:00:00 2001 From: //de Date: Mon, 6 Apr 2015 13:41:38 -0700 Subject: [PATCH 35/97] except I wasn't on a branch --- celluloid-io.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index 55f551a..e2cdc78 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |gem| gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") gem.require_paths = ["lib"] - gem.add_dependency 'celluloid', '>= 0.17.0' + gem.add_dependency 'celluloid', '>= 0.16.0' gem.add_dependency 'nio4r', '>= 1.1.0' gem.add_development_dependency 'rake' From f76709f3a9177190a7e15d49263c6db40faa0def Mon Sep 17 00:00:00 2001 From: //de Date: Mon, 6 Apr 2015 15:01:04 -0700 Subject: [PATCH 36/97] Fix issues with rspec. Back to green --- Gemfile | 8 +++++++- spec/celluloid/io/reactor_spec.rb | 2 +- spec/celluloid/io/ssl_server_spec.rb | 2 +- spec/celluloid/io/tcp_server_spec.rb | 2 +- spec/celluloid/io/tcp_socket_spec.rb | 4 ++-- spec/celluloid/io/udp_socket_spec.rb | 2 +- spec/celluloid/io/unix_server_spec.rb | 2 +- spec/celluloid/io/unix_socket_spec.rb | 2 +- 8 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Gemfile b/Gemfile index 52ce11f..1b6e71b 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,11 @@ source 'https://rubygems.org' gemspec +group :test do + gem 'benchmark_suite' + gem 'rspec', '~> 3.2' + gem 'rspec-retry' +end + gem 'coveralls', require: false -gem 'celluloid', github: 'celluloid/celluloid', branch: 'master' +gem 'celluloid', github: 'celluloid/celluloid', branch: 'master' \ No newline at end of file diff --git a/spec/celluloid/io/reactor_spec.rb b/spec/celluloid/io/reactor_spec.rb index 9c63990..f552683 100644 --- a/spec/celluloid/io/reactor_spec.rb +++ b/spec/celluloid/io/reactor_spec.rb @@ -29,7 +29,7 @@ end end - expect(handle).to be_true + expect(handle).to be_truthy server.close peer.close diff --git a/spec/celluloid/io/ssl_server_spec.rb b/spec/celluloid/io/ssl_server_spec.rb index 1a53f21..fda8712 100644 --- a/spec/celluloid/io/ssl_server_spec.rb +++ b/spec/celluloid/io/ssl_server_spec.rb @@ -25,7 +25,7 @@ context "inside Celluloid::IO" do it "should be evented" do with_ssl_server do |subject| - within_io_actor { Celluloid::IO.evented? }.should be_true + within_io_actor { Celluloid::IO.evented? }.should be_truthy end end diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index bfb3437..17a19d9 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -11,7 +11,7 @@ context "inside Celluloid::IO" do it "should be evented" do with_tcp_server do |subject| - within_io_actor { Celluloid::IO.evented? }.should be_true + within_io_actor { Celluloid::IO.evented? }.should be_truthy end end diff --git a/spec/celluloid/io/tcp_socket_spec.rb b/spec/celluloid/io/tcp_socket_spec.rb index e2e9ddf..a904c4c 100644 --- a/spec/celluloid/io/tcp_socket_spec.rb +++ b/spec/celluloid/io/tcp_socket_spec.rb @@ -23,7 +23,7 @@ thread = Thread.new { server.accept } value = within_io_actor { Celluloid::IO::TCPSocket.open(example_addr, example_port) { true } } - value.should be_true + value.should be_truthy server.close thread.terminate @@ -47,7 +47,7 @@ it "should be evented" do with_connected_sockets do |subject| - within_io_actor { Celluloid::IO.evented? }.should be_true + within_io_actor { Celluloid::IO.evented? }.should be_truthy end end diff --git a/spec/celluloid/io/udp_socket_spec.rb b/spec/celluloid/io/udp_socket_spec.rb index d7d4769..78e17c5 100644 --- a/spec/celluloid/io/udp_socket_spec.rb +++ b/spec/celluloid/io/udp_socket_spec.rb @@ -12,7 +12,7 @@ context "inside Celluloid::IO" do it "should be evented" do - within_io_actor { Celluloid::IO.evented? }.should be_true + within_io_actor { Celluloid::IO.evented? }.should be_truthy end it "sends and receives packets" do diff --git a/spec/celluloid/io/unix_server_spec.rb b/spec/celluloid/io/unix_server_spec.rb index a0f9fdc..328972e 100644 --- a/spec/celluloid/io/unix_server_spec.rb +++ b/spec/celluloid/io/unix_server_spec.rb @@ -11,7 +11,7 @@ context "inside Celluloid::IO" do it "should be evented" do with_unix_server do |subject| - within_io_actor { Celluloid::IO.evented? }.should be_true + within_io_actor { Celluloid::IO.evented? }.should be_truthy end end diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index 132d18d..a1df270 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -25,7 +25,7 @@ it "should be evented" do with_connected_unix_sockets do |subject| - within_io_actor { Celluloid::IO.evented? }.should be_true + within_io_actor { Celluloid::IO.evented? }.should be_truthy end end From 64081f188cf88cb83f4a3da538d8c7911dffd96e Mon Sep 17 00:00:00 2001 From: //de Date: Mon, 13 Apr 2015 17:05:13 -0700 Subject: [PATCH 37/97] use Celluloid::Mailbox::Evented convention --- lib/celluloid/io/mailbox.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/celluloid/io/mailbox.rb b/lib/celluloid/io/mailbox.rb index 1fe2cec..77acd7f 100644 --- a/lib/celluloid/io/mailbox.rb +++ b/lib/celluloid/io/mailbox.rb @@ -1,7 +1,7 @@ module Celluloid module IO # An alternative implementation of Celluloid::Mailbox using Reactor - class Mailbox < Celluloid::EventedMailbox + class Mailbox < Celluloid::Mailbox::Evented def initialize super(Reactor) end From 0af67a640b3e50aaa9ac5537fdcf36b38199951e Mon Sep 17 00:00:00 2001 From: //de Date: Mon, 13 Apr 2015 17:10:15 -0700 Subject: [PATCH 38/97] regularity of heading breaks ( seriously ) and add change --- CHANGES.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 17ecd88..912c82f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,21 +1,25 @@ +HEAD +----- +* Adjust class name for Celluloid::Mailbox::Evented, per 0.17.0 of Celluloid. + 0.16.2 (2015-01-30) -------------------- +----- * More TCPSocket compatibility fixes * Ensure monitors are closed when tasks resume * Fix Errno::EAGAIN handling in Stream#syswrite 0.16.1 (2014-10-08) -------------------- +----- * Revert read/write interest patch as it caused file descriptor leaks 0.16.0 (2014-09-04) -------------------- +----- * Fix bug handling simultaneous read/write interests * Use Resolv::DNS::Config to obtain nameservers * Celluloid::IO.copy_stream support (uses a background thread) 0.15.0 (2013-09-04) -------------------- +----- * Improved DNS resolver with less NIH and more Ruby stdlib goodness * Better match Ruby stdlib TCPServer API * Add missing #send and #recv on Celluloid::IO::TCPSocket @@ -23,16 +27,16 @@ * Add missing #peeraddr method on Celluloid::IO::SSLSocket 0.14.0 (2013-05-07) -------------------- +----- * Add `close_read`/`close_write` delegates for rack-hijack support * Depend on EventedMailbox from core 0.13.1 ------- +----- * Remove overhead for `wait_readable`/`wait_writable` 0.13.0 ------- +----- * Support for many, many more IO methods, particularly line-oriented methods like #gets, #readline, and #readlines * Initial SSL support via Celluloid::IO::SSLSocket and @@ -42,15 +46,15 @@ * Celluloid 0.13 compatibility fixes 0.12.0 ------- +----- * Tracking release for Celluloid 0.12.0 0.11.0 ------- +----- * "Unofficial" SSL support (via nio4r 0.4.0) 0.10.0 ------- +----- * Read/write operations are now atomic across tasks * True non-blocking connect support * Non-blocking DNS resolution support From 9e771f4e780332b0da3de1e953bb9110260774f9 Mon Sep 17 00:00:00 2001 From: //de Date: Mon, 13 Apr 2015 17:19:27 -0700 Subject: [PATCH 39/97] depend on the new 0.17.0 Celluloid prerelease --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 1b6e71b..7309f69 100644 --- a/Gemfile +++ b/Gemfile @@ -8,4 +8,4 @@ group :test do end gem 'coveralls', require: false -gem 'celluloid', github: 'celluloid/celluloid', branch: 'master' \ No newline at end of file +gem 'celluloid', github: 'celluloid/celluloid', branch: '0.17.0-prerelease' \ No newline at end of file From def2e1efa05637041f4853c5f1198c9066feeb23 Mon Sep 17 00:00:00 2001 From: //de Date: Thu, 16 Apr 2015 15:36:49 -0700 Subject: [PATCH 40/97] standardize jRuby detection unless the actual desire is to obtain the jRuby version itself --- lib/celluloid/io/tcp_socket.rb | 2 +- lib/celluloid/io/version.rb | 2 +- spec/celluloid/io/ssl_socket_spec.rb | 10 +++++----- spec/celluloid/io/unix_server_spec.rb | 2 +- spec/celluloid/io/unix_socket_spec.rb | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/celluloid/io/tcp_socket.rb b/lib/celluloid/io/tcp_socket.rb index f6d0bed..624e3c1 100644 --- a/lib/celluloid/io/tcp_socket.rb +++ b/lib/celluloid/io/tcp_socket.rb @@ -86,7 +86,7 @@ def initialize(remote_host, remote_port = nil, local_host = nil, local_port = ni # HAX: for some reason we need to finish_connect ourselves on JRuby # This logic is unnecessary but JRuby still throws Errno::EINPROGRESS # if we retry the non-blocking connect instead of just finishing it - retry unless defined?(JRUBY_VERSION) && @socket.to_channel.finish_connect + retry unless RUBY_PLATFORM == 'java' && @socket.to_channel.finish_connect rescue Errno::EISCONN # We're now connected! Yay exceptions for flow control # NOTE: This is the approach the Ruby stdlib docs suggest ;_; diff --git a/lib/celluloid/io/version.rb b/lib/celluloid/io/version.rb index 90c6efe..1416384 100644 --- a/lib/celluloid/io/version.rb +++ b/lib/celluloid/io/version.rb @@ -1,5 +1,5 @@ module Celluloid module IO - VERSION = "0.16.2" + VERSION = "0.16.5" end end diff --git a/spec/celluloid/io/ssl_socket_spec.rb b/spec/celluloid/io/ssl_socket_spec.rb index 86df511..09d5acb 100644 --- a/spec/celluloid/io/ssl_socket_spec.rb +++ b/spec/celluloid/io/ssl_socket_spec.rb @@ -81,7 +81,7 @@ end it "starts SSL on a connected TCP socket" do - pending "JRuby support" if defined?(JRUBY_VERSION) + pending "JRuby support" if RUBY_PLATFORM == 'java' with_raw_sockets do |client, peer| within_io_actor do peer << request @@ -118,7 +118,7 @@ end it "starts SSL on a connected TCP socket" do - pending "JRuby support" if defined?(JRUBY_VERSION) + pending "JRuby support" if RUBY_PLATFORM == 'java' with_raw_sockets do |client, peer| peer << request client.read(request.size).should eq(request) @@ -143,7 +143,7 @@ it "knows its cert" do # FIXME: seems bad? o_O - pending "wtf is wrong with this on JRuby" if defined? JRUBY_VERSION + pending "wtf is wrong with this on JRuby" if RUBY_PLATFORM == 'java' with_ssl_sockets do |ssl_client| ssl_client.cert.to_der.should eq(client_cert.to_der) end @@ -171,7 +171,7 @@ it "knows its client_ca" do # jruby-openssl does not implement this method - pending "jruby-openssl support" if defined? JRUBY_VERSION + pending "jruby-openssl support" if RUBY_PLATFORM == 'java' with_ssl_sockets do |ssl_client| ssl_client.client_ca.should eq(ssl_client.to_io.client_ca) @@ -180,7 +180,7 @@ it "verifies peer certificates" do # FIXME: JRuby seems to be giving the wrong result here o_O - pending "jruby-openssl support" if defined? JRUBY_VERSION + pending "jruby-openssl support" if RUBY_PLATFORM == 'java' with_ssl_sockets do |ssl_client, ssl_peer| ssl_client.verify_result.should eq(OpenSSL::X509::V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) diff --git a/spec/celluloid/io/unix_server_spec.rb b/spec/celluloid/io/unix_server_spec.rb index 328972e..3813498 100644 --- a/spec/celluloid/io/unix_server_spec.rb +++ b/spec/celluloid/io/unix_server_spec.rb @@ -3,7 +3,7 @@ describe Celluloid::IO::UNIXServer do describe "#accept" do before do - pending "JRuby support" if defined?(JRUBY_VERSION) + pending "JRuby support" if RUBY_PLATFORM == 'java' end let(:payload) { 'ohai' } diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index a1df270..d568ee0 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -2,7 +2,7 @@ describe Celluloid::IO::UNIXSocket do before do - pending "JRuby support" if defined?(JRUBY_VERSION) + pending "JRuby support" if RUBY_PLATFORM == 'java' end let(:payload) { 'ohai' } From e15ba591da1973cbdafd9e1fd03ffd6e33254419 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 17 Apr 2015 20:07:37 -0700 Subject: [PATCH 41/97] Delegate #post_connection_check on Celluloid::IO::SSLSocket This method is needed to perform hostname verification, without which MitM attacks are possible using any cert rooted in the local truststore. --- lib/celluloid/io/ssl_socket.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/celluloid/io/ssl_socket.rb b/lib/celluloid/io/ssl_socket.rb index b860a61..8a8bdb9 100644 --- a/lib/celluloid/io/ssl_socket.rb +++ b/lib/celluloid/io/ssl_socket.rb @@ -6,8 +6,20 @@ module IO class SSLSocket < Stream extend Forwardable - def_delegators :@socket, :read_nonblock, :write_nonblock, :close, :closed?, - :cert, :cipher, :client_ca, :peer_cert, :peer_cert_chain, :verify_result, :peeraddr, :sync_close= + def_delegators :@socket, + :read_nonblock, + :write_nonblock, + :close, + :closed?, + :cert, + :cipher, + :client_ca, + :peeraddr, + :peer_cert, + :peer_cert_chain, + :post_connection_check, + :verify_result, + :sync_close= def initialize(io, ctx = OpenSSL::SSL::SSLContext.new) super() From 6b20c0947f39ba1c711ea663a4dcdfe61ba4326e Mon Sep 17 00:00:00 2001 From: //de Date: Sat, 18 Apr 2015 08:27:44 -0700 Subject: [PATCH 42/97] Fix to match expectations elsewhere. --- lib/celluloid/io/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/celluloid/io/version.rb b/lib/celluloid/io/version.rb index 90c6efe..1416384 100644 --- a/lib/celluloid/io/version.rb +++ b/lib/celluloid/io/version.rb @@ -1,5 +1,5 @@ module Celluloid module IO - VERSION = "0.16.2" + VERSION = "0.16.5" end end From 3d3f10a467c7b900ab4fdec7dec11901fea6b4b4 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 21 Apr 2015 19:38:26 +1200 Subject: [PATCH 43/97] Handle MRI's Errno::EALREADY in connect_nonblock. Fixes #138 In certain high-load situations in RubyDNS (thousands of connections), it has been observed that `Socket#connect_nonblock` sometimes fails with `Errno::EALREADY`: a connection is already in progress for the specified socket. In this case I believe it is prudent that we wait for the socket to become writable and then attempt to `connect_nonblock` again, at which point the connection should either fail or give `Errno::EISCONN`. --- lib/celluloid/io/tcp_socket.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/celluloid/io/tcp_socket.rb b/lib/celluloid/io/tcp_socket.rb index f6d0bed..fe7ca6d 100644 --- a/lib/celluloid/io/tcp_socket.rb +++ b/lib/celluloid/io/tcp_socket.rb @@ -80,7 +80,9 @@ def initialize(remote_host, remote_port = nil, local_host = nil, local_port = ni begin @socket.connect_nonblock Socket.sockaddr_in(remote_port, @addr.to_s) - rescue Errno::EINPROGRESS + rescue Errno::EINPROGRESS, Errno::EALREADY + # JRuby raises EINPROGRESS, MRI raises EALREADY + wait_writable # HAX: for some reason we need to finish_connect ourselves on JRuby From 4f7b8e9e752cdfe38cc04ff9ef0cb4a0c2344e98 Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 1 May 2015 16:22:10 -0700 Subject: [PATCH 44/97] implement Celluloid::Sync --- celluloid-io.gemspec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index e2cdc78..1bc22fc 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -1,5 +1,5 @@ # -*- encoding: utf-8 -*- -require File.expand_path('../lib/celluloid/io/version', __FILE__) +require File.expand_path("../culture/sync", __FILE__) Gem::Specification.new do |gem| gem.name = "celluloid-io" @@ -16,7 +16,8 @@ Gem::Specification.new do |gem| gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") gem.require_paths = ["lib"] - gem.add_dependency 'celluloid', '>= 0.16.0' + Celluloid::Sync.gems(gem) + gem.add_dependency 'nio4r', '>= 1.1.0' gem.add_development_dependency 'rake' From 292d0db36ff3f589e0339bf930649cde7def2cef Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 1 May 2015 16:27:02 -0700 Subject: [PATCH 45/97] use Celluloid::Sync --- Gemfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 7309f69..46d1990 100644 --- a/Gemfile +++ b/Gemfile @@ -1,11 +1,11 @@ +require File.expand_path("../culture/sync", __FILE__) source 'https://rubygems.org' + gemspec group :test do gem 'benchmark_suite' gem 'rspec', '~> 3.2' - gem 'rspec-retry' end -gem 'coveralls', require: false -gem 'celluloid', github: 'celluloid/celluloid', branch: '0.17.0-prerelease' \ No newline at end of file +Celluloid::Sync.gems(self) From 3254d499e6c9ee905061511684cbe9b437701ea9 Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 1 May 2015 16:36:08 -0700 Subject: [PATCH 46/97] add Celluloid::Sync --- .gitmodules | 3 +++ culture | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 culture diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7f72185 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "culture"] + path = culture + url = http://github.com/celluloid/culture.git diff --git a/culture b/culture new file mode 160000 index 0000000..eae9589 --- /dev/null +++ b/culture @@ -0,0 +1 @@ +Subproject commit eae95897b1e1eeeaf4a20fa82035791b99d576bb From b4d4f96ec4c9f763a9df868674e2b9c357fe13ca Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 1 May 2015 17:00:04 -0700 Subject: [PATCH 47/97] use same parameters as Celluloid --- .travis.yml | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index d98876b..b4566c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,34 @@ script: rake ci +language: ruby rvm: - - 1.9.3 - - 2.0.0 - - 2.1.1 - - ruby-head + - 2.2.0 + - 2.2.2 - jruby + - ruby-head - jruby-head - rbx-2 +# TODO: Put these back: +# * CELLULOID_TASK_CLASS=Fibered +# * CELLULOID_TASK_CLASS=Threaded +# For right now the imporant thing is to test BACKPORTED mode: + matrix: allow_failures: + - rvm: rbx-2 - rvm: ruby-head - - rvm: jruby - rvm: jruby-head - - rvm: rbx-2 + - env: CELLULOID_BACKPORTED=true + +env: + matrix: + - CELLULOID_BACKPORTED=true + - CELLULOID_BACKPORTED=false + global: + - NUMBER_OF_PROCESSORS=2 CELLULOID_CONFIG_FILE=.env-ci notifications: irc: "irc.freenode.org#celluloid" + +sudo: false +install: bundle install --retry=3 --without=development From 29302c2f5a8988461be261c101618caf1b575349 Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 1 May 2015 17:02:55 -0700 Subject: [PATCH 48/97] use updated Celluloid::Sync --- culture | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/culture b/culture index eae9589..aec5f9f 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit eae95897b1e1eeeaf4a20fa82035791b99d576bb +Subproject commit aec5f9f03c5f020f89f03c4614aaeada32c6fb35 From 31de19da45f8d0dde338580ee4a1589a1acee000 Mon Sep 17 00:00:00 2001 From: //de Date: Sun, 3 May 2015 20:35:52 -0700 Subject: [PATCH 49/97] update culture/sync --- culture | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/culture b/culture index aec5f9f..1670c80 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit aec5f9f03c5f020f89f03c4614aaeada32c6fb35 +Subproject commit 1670c80e8f0c584a2c1f9eaf6ee41e79586b68a8 From 7dc37f7c9100d068e5f8857d6940adbc91be4522 Mon Sep 17 00:00:00 2001 From: //de Date: Wed, 6 May 2015 02:23:07 -0700 Subject: [PATCH 50/97] remove retry RE: celluloid/culture#7 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b4566c1..a393baa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,4 +31,4 @@ notifications: irc: "irc.freenode.org#celluloid" sudo: false -install: bundle install --retry=3 --without=development +install: bundle install --without=development From f898cd7edb0c4f5d4227a7206690e695ec680c93 Mon Sep 17 00:00:00 2001 From: //de Date: Thu, 7 May 2015 21:44:54 -0700 Subject: [PATCH 51/97] Much tighter Gemfile. --- Gemfile | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 46d1990..2e4054c 100644 --- a/Gemfile +++ b/Gemfile @@ -1,11 +1,2 @@ require File.expand_path("../culture/sync", __FILE__) -source 'https://rubygems.org' - -gemspec - -group :test do - gem 'benchmark_suite' - gem 'rspec', '~> 3.2' -end - -Celluloid::Sync.gems(self) +Celluloid::Sync::Gemfile[self] From 115e5ba408905768f8291d2a912ebda1395c9eb5 Mon Sep 17 00:00:00 2001 From: //de Date: Thu, 7 May 2015 21:53:58 -0700 Subject: [PATCH 52/97] sync Sync:: --- culture | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/culture b/culture index 1670c80..005c416 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit 1670c80e8f0c584a2c1f9eaf6ee41e79586b68a8 +Subproject commit 005c4165a16c1af12422849576bbc5bb60e17673 From 5eae4bb0fa1da05ec831a60f47a76c0457451095 Mon Sep 17 00:00:00 2001 From: //de Date: Thu, 7 May 2015 22:13:35 -0700 Subject: [PATCH 53/97] different interface to Sync --- celluloid-io.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index 1bc22fc..647d0d8 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |gem| gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") gem.require_paths = ["lib"] - Celluloid::Sync.gems(gem) + Celluloid::Sync::Gemspec[gem] gem.add_dependency 'nio4r', '>= 1.1.0' From daf1e775d60d027cae90bae1ce780d14e2a0baa4 Mon Sep 17 00:00:00 2001 From: //de Date: Thu, 7 May 2015 22:13:57 -0700 Subject: [PATCH 54/97] more succint gemspec --- celluloid-io.gemspec | 3 --- 1 file changed, 3 deletions(-) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index 647d0d8..72a11fd 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -20,9 +20,6 @@ Gem::Specification.new do |gem| gem.add_dependency 'nio4r', '>= 1.1.0' - gem.add_development_dependency 'rake' - gem.add_development_dependency 'rspec', '~> 2.14.0' - gem.add_development_dependency 'benchmark_suite' gem.add_development_dependency 'guard-rspec' gem.add_development_dependency 'rb-fsevent', '~> 0.9.1' if RUBY_PLATFORM =~ /darwin/ end From bec2c47dc1dd3b51ccaaed6bd1070808f5378712 Mon Sep 17 00:00:00 2001 From: //de Date: Thu, 7 May 2015 23:04:43 -0700 Subject: [PATCH 55/97] transpec conversion of tests --- spec/celluloid/io/dns_resolver_spec.rb | 14 ++++----- spec/celluloid/io/ssl_server_spec.rb | 14 ++++----- spec/celluloid/io/ssl_socket_spec.rb | 42 +++++++++++++------------- spec/celluloid/io/tcp_server_spec.rb | 12 ++++---- spec/celluloid/io/tcp_socket_spec.rb | 36 +++++++++++----------- spec/celluloid/io/udp_socket_spec.rb | 8 ++--- spec/celluloid/io/unix_server_spec.rb | 12 ++++---- spec/celluloid/io/unix_socket_spec.rb | 32 ++++++++++---------- 8 files changed, 85 insertions(+), 85 deletions(-) diff --git a/spec/celluloid/io/dns_resolver_spec.rb b/spec/celluloid/io/dns_resolver_spec.rb index 87ca2c7..edae36e 100644 --- a/spec/celluloid/io/dns_resolver_spec.rb +++ b/spec/celluloid/io/dns_resolver_spec.rb @@ -5,14 +5,14 @@ it 'resolves hostnames statically from hosts file without nameservers' do # /etc/resolv.conf doesn't exist on Mac OSX when no networking is # disabled, thus .nameservers would return nil - Celluloid::IO::DNSResolver.should_receive(:nameservers).at_most(:once) { nil } + expect(Celluloid::IO::DNSResolver).to receive(:nameservers).at_most(:once) { nil } resolver = Celluloid::IO::DNSResolver.new - resolver.resolve('localhost').should eq Resolv::IPv4.create("127.0.0.1") + expect(resolver.resolve('localhost')).to eq Resolv::IPv4.create("127.0.0.1") end it 'resolves hostnames' do resolver = Celluloid::IO::DNSResolver.new - resolver.resolve('localhost').should eq Resolv::IPv4.create("127.0.0.1") + expect(resolver.resolve('localhost')).to eq Resolv::IPv4.create("127.0.0.1") end it "resolves domain names" do @@ -26,17 +26,17 @@ resolver = Celluloid::IO::DNSResolver.new results = resolver.resolve("www.google.com") if results.is_a?(Array) - results.all? {|i| i.should be_an_instance_of(Resolv::IPv4) } + results.all? {|i| expect(i).to be_an_instance_of(Resolv::IPv4) } else - results.should be_an_instance_of(Resolv::IPv4) + expect(results).to be_an_instance_of(Resolv::IPv4) end # www.yahoo.com will be resolved randomly whether multiple or # single entry. results = resolver.resolve("www.yahoo.com") if results.is_a?(Array) - results.all? {|i| i.should be_an_instance_of(Resolv::IPv4) } + results.all? {|i| expect(i).to be_an_instance_of(Resolv::IPv4) } else - results.should be_an_instance_of(Resolv::IPv4) + expect(results).to be_an_instance_of(Resolv::IPv4) end end end diff --git a/spec/celluloid/io/ssl_server_spec.rb b/spec/celluloid/io/ssl_server_spec.rb index fda8712..04cb820 100644 --- a/spec/celluloid/io/ssl_server_spec.rb +++ b/spec/celluloid/io/ssl_server_spec.rb @@ -25,7 +25,7 @@ context "inside Celluloid::IO" do it "should be evented" do with_ssl_server do |subject| - within_io_actor { Celluloid::IO.evented? }.should be_truthy + expect(within_io_actor { Celluloid::IO.evented? }).to be_truthy end end @@ -36,11 +36,11 @@ OpenSSL::SSL::SSLSocket.new(raw, client_context).connect end peer = within_io_actor { subject.accept } - peer.should be_a Celluloid::IO::SSLSocket + expect(peer).to be_a Celluloid::IO::SSLSocket client = thread.value client.write payload - peer.read(payload.size).should eq payload + expect(peer.read(payload.size)).to eq payload end end end @@ -48,7 +48,7 @@ context "outside Celluloid::IO" do it "should be blocking" do with_ssl_server do |subject| - Celluloid::IO.should_not be_evented + expect(Celluloid::IO).not_to be_evented end end @@ -59,11 +59,11 @@ OpenSSL::SSL::SSLSocket.new(raw, client_context).connect end peer = subject.accept - peer.should be_a Celluloid::IO::SSLSocket + expect(peer).to be_a Celluloid::IO::SSLSocket client = thread.value client.write payload - peer.read(payload.size).should eq payload + expect(peer.read(payload.size)).to eq payload end end end @@ -73,7 +73,7 @@ it "should auto-wrap a raw ::TCPServer" do raw_server = ::TCPServer.new(example_addr, example_ssl_port) with_ssl_server(raw_server) do |ssl_server| - ssl_server.tcp_server.class.should == Celluloid::IO::TCPServer + expect(ssl_server.tcp_server.class).to eq(Celluloid::IO::TCPServer) end end end diff --git a/spec/celluloid/io/ssl_socket_spec.rb b/spec/celluloid/io/ssl_socket_spec.rb index 09d5acb..81761e9 100644 --- a/spec/celluloid/io/ssl_socket_spec.rb +++ b/spec/celluloid/io/ssl_socket_spec.rb @@ -72,10 +72,10 @@ with_ssl_sockets do |ssl_client, ssl_peer| within_io_actor do ssl_peer << request - ssl_client.read(request.size).should eq(request) + expect(ssl_client.read(request.size)).to eq(request) ssl_client << response - ssl_peer.read(response.size).should eq(response) + expect(ssl_peer.read(response.size)).to eq(response) end end end @@ -85,22 +85,22 @@ with_raw_sockets do |client, peer| within_io_actor do peer << request - client.read(request.size).should eq(request) + expect(client.read(request.size)).to eq(request) client << response - peer.read(response.size).should eq(response) + expect(peer.read(response.size)).to eq(response) # now that we've written bytes, upgrade to SSL client_thread = Thread.new { OpenSSL::SSL::SSLSocket.new(client).connect } ssl_peer = Celluloid::IO::SSLSocket.new peer, server_context - ssl_peer.should eq(ssl_peer.accept) + expect(ssl_peer).to eq(ssl_peer.accept) ssl_client = client_thread.value ssl_peer << request - ssl_client.read(request.size).should eq(request) + expect(ssl_client.read(request.size)).to eq(request) ssl_client << response - ssl_peer.read(response.size).should eq(response) + expect(ssl_peer.read(response.size)).to eq(response) end end end @@ -110,10 +110,10 @@ it "connects to SSL servers over TCP" do with_ssl_sockets do |ssl_client, ssl_peer| ssl_peer << request - ssl_client.read(request.size).should eq(request) + expect(ssl_client.read(request.size)).to eq(request) ssl_client << response - ssl_peer.read(response.size).should eq(response) + expect(ssl_peer.read(response.size)).to eq(response) end end @@ -121,22 +121,22 @@ pending "JRuby support" if RUBY_PLATFORM == 'java' with_raw_sockets do |client, peer| peer << request - client.read(request.size).should eq(request) + expect(client.read(request.size)).to eq(request) client << response - peer.read(response.size).should eq(response) + expect(peer.read(response.size)).to eq(response) # now that we've written bytes, upgrade to SSL client_thread = Thread.new { OpenSSL::SSL::SSLSocket.new(client).connect } ssl_peer = Celluloid::IO::SSLSocket.new peer, server_context - ssl_peer.should eq(ssl_peer.accept) + expect(ssl_peer).to eq(ssl_peer.accept) ssl_client = client_thread.value ssl_peer << request - ssl_client.read(request.size).should eq(request) + expect(ssl_client.read(request.size)).to eq(request) ssl_client << response - ssl_peer.read(response.size).should eq(response) + expect(ssl_peer.read(response.size)).to eq(response) end end end @@ -145,27 +145,27 @@ # FIXME: seems bad? o_O pending "wtf is wrong with this on JRuby" if RUBY_PLATFORM == 'java' with_ssl_sockets do |ssl_client| - ssl_client.cert.to_der.should eq(client_cert.to_der) + expect(ssl_client.cert.to_der).to eq(client_cert.to_der) end end it "knows its peer_cert" do with_ssl_sockets do |ssl_client| - ssl_client.peer_cert.to_der.should eq(ssl_client.to_io.peer_cert.to_der) + expect(ssl_client.peer_cert.to_der).to eq(ssl_client.to_io.peer_cert.to_der) end end it "knows its peer_cert_chain" do with_ssl_sockets do |ssl_client| - ssl_client.peer_cert_chain.zip(ssl_client.to_io.peer_cert_chain).map do |c1, c2| + expect(ssl_client.peer_cert_chain.zip(ssl_client.to_io.peer_cert_chain).map do |c1, c2| c1.to_der == c2.to_der - end.should be_all + end).to be_all end end it "knows its cipher" do with_ssl_sockets do |ssl_client| - ssl_client.cipher.should eq(ssl_client.to_io.cipher) + expect(ssl_client.cipher).to eq(ssl_client.to_io.cipher) end end @@ -174,7 +174,7 @@ pending "jruby-openssl support" if RUBY_PLATFORM == 'java' with_ssl_sockets do |ssl_client| - ssl_client.client_ca.should eq(ssl_client.to_io.client_ca) + expect(ssl_client.client_ca).to eq(ssl_client.to_io.client_ca) end end @@ -183,7 +183,7 @@ pending "jruby-openssl support" if RUBY_PLATFORM == 'java' with_ssl_sockets do |ssl_client, ssl_peer| - ssl_client.verify_result.should eq(OpenSSL::X509::V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) + expect(ssl_client.verify_result).to eq(OpenSSL::X509::V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) end end diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index 17a19d9..038cf8f 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -11,7 +11,7 @@ context "inside Celluloid::IO" do it "should be evented" do with_tcp_server do |subject| - within_io_actor { Celluloid::IO.evented? }.should be_truthy + expect(within_io_actor { Celluloid::IO.evented? }).to be_truthy end end @@ -19,18 +19,18 @@ with_tcp_server do |subject| thread = Thread.new { TCPSocket.new(example_addr, example_port) } peer = within_io_actor { subject.accept } - peer.should be_a Celluloid::IO::TCPSocket + expect(peer).to be_a Celluloid::IO::TCPSocket client = thread.value client.write payload - peer.read(payload.size).should eq payload + expect(peer.read(payload.size)).to eq payload end end context "outside Celluloid::IO" do it "should be blocking" do with_tcp_server do |subject| - Celluloid::IO.should_not be_evented + expect(Celluloid::IO).not_to be_evented end end @@ -38,11 +38,11 @@ with_tcp_server do |subject| thread = Thread.new { TCPSocket.new(example_addr, example_port) } peer = subject.accept - peer.should be_a Celluloid::IO::TCPSocket + expect(peer).to be_a Celluloid::IO::TCPSocket client = thread.value client.write payload - peer.read(payload.size).should eq payload + expect(peer.read(payload.size)).to eq payload end end end diff --git a/spec/celluloid/io/tcp_socket_spec.rb b/spec/celluloid/io/tcp_socket_spec.rb index a904c4c..d94f0eb 100644 --- a/spec/celluloid/io/tcp_socket_spec.rb +++ b/spec/celluloid/io/tcp_socket_spec.rb @@ -11,7 +11,7 @@ thread = Thread.new { server.accept } socket = within_io_actor { Celluloid::IO::TCPSocket.open(example_addr, example_port) } - socket.should be_a(Celluloid::IO::TCPSocket) + expect(socket).to be_a(Celluloid::IO::TCPSocket) server.close thread.terminate @@ -23,7 +23,7 @@ thread = Thread.new { server.accept } value = within_io_actor { Celluloid::IO::TCPSocket.open(example_addr, example_port) { true } } - value.should be_truthy + expect(value).to be_truthy server.close thread.terminate @@ -38,7 +38,7 @@ peer = thread.value peer << payload - within_io_actor { socket.read(payload.size) }.should eq payload + expect(within_io_actor { socket.read(payload.size) }).to eq payload server.close socket.close @@ -47,56 +47,56 @@ it "should be evented" do with_connected_sockets do |subject| - within_io_actor { Celluloid::IO.evented? }.should be_truthy + expect(within_io_actor { Celluloid::IO.evented? }).to be_truthy end end it "read complete payload when nil size is given to #read" do with_connected_sockets do |subject, peer| peer << payload - within_io_actor { subject.read(nil) }.should eq payload + expect(within_io_actor { subject.read(nil) }).to eq payload end end it "read complete payload when no size is given to #read" do with_connected_sockets do |subject, peer| peer << payload - within_io_actor { subject.read }.should eq payload + expect(within_io_actor { subject.read }).to eq payload end end it "reads data" do with_connected_sockets do |subject, peer| peer << payload - within_io_actor { subject.read(payload.size) }.should eq payload + expect(within_io_actor { subject.read(payload.size) }).to eq payload end end it "reads data in binary encoding" do with_connected_sockets do |subject, peer| peer << payload - within_io_actor { subject.read(payload.size).encoding }.should eq Encoding::BINARY + expect(within_io_actor { subject.read(payload.size).encoding }).to eq Encoding::BINARY end end it "reads partial data" do with_connected_sockets do |subject, peer| peer << payload * 2 - within_io_actor { subject.readpartial(payload.size) }.should eq payload + expect(within_io_actor { subject.readpartial(payload.size) }).to eq payload end end it "reads partial data in binary encoding" do with_connected_sockets do |subject, peer| peer << payload * 2 - within_io_actor { subject.readpartial(payload.size).encoding }.should eq Encoding::BINARY + expect(within_io_actor { subject.readpartial(payload.size).encoding }).to eq Encoding::BINARY end end it "writes data" do with_connected_sockets do |subject, peer| within_io_actor { subject << payload } - peer.read(payload.size).should eq payload + expect(peer.read(payload.size)).to eq payload end end @@ -112,7 +112,7 @@ started_at = Time.now Thread.new{ sleep 0.5; peer.close; } within_io_actor { subject.eof? } - (Time.now - started_at).should > 0.5 + expect(Time.now - started_at).to be > 0.5 end end @@ -124,7 +124,7 @@ within_io_actor { subject.read(1) Celluloid.timeout(0.5) { - subject.eof?.should be_false + expect(subject.eof?).to be_falsey } } }.to raise_error(Celluloid::Task::TimeoutError) @@ -185,7 +185,7 @@ peer = thread.value peer << payload - socket.read(payload.size).should eq payload + expect(socket.read(payload.size)).to eq payload server.close socket.close @@ -194,28 +194,28 @@ it "should be blocking" do with_connected_sockets do |subject| - Celluloid::IO.should_not be_evented + expect(Celluloid::IO).not_to be_evented end end it "reads data" do with_connected_sockets do |subject, peer| peer << payload - subject.read(payload.size).should eq payload + expect(subject.read(payload.size)).to eq payload end end it "reads partial data" do with_connected_sockets do |subject, peer| peer << payload * 2 - subject.readpartial(payload.size).should eq payload + expect(subject.readpartial(payload.size)).to eq payload end end it "writes data" do with_connected_sockets do |subject, peer| subject << payload - peer.read(payload.size).should eq payload + expect(peer.read(payload.size)).to eq payload end end end diff --git a/spec/celluloid/io/udp_socket_spec.rb b/spec/celluloid/io/udp_socket_spec.rb index 78e17c5..17c95a3 100644 --- a/spec/celluloid/io/udp_socket_spec.rb +++ b/spec/celluloid/io/udp_socket_spec.rb @@ -12,25 +12,25 @@ context "inside Celluloid::IO" do it "should be evented" do - within_io_actor { Celluloid::IO.evented? }.should be_truthy + expect(within_io_actor { Celluloid::IO.evented? }).to be_truthy end it "sends and receives packets" do within_io_actor do subject.send payload, 0, example_addr, example_port - subject.recvfrom(payload.size).first.should == payload + expect(subject.recvfrom(payload.size).first).to eq(payload) end end end context "outside Celluloid::IO" do it "should be blocking" do - Celluloid::IO.should_not be_evented + expect(Celluloid::IO).not_to be_evented end it "sends and receives packets" do subject.send payload, 0, example_addr, example_port - subject.recvfrom(payload.size).first.should == payload + expect(subject.recvfrom(payload.size).first).to eq(payload) end end end diff --git a/spec/celluloid/io/unix_server_spec.rb b/spec/celluloid/io/unix_server_spec.rb index 3813498..6484c8b 100644 --- a/spec/celluloid/io/unix_server_spec.rb +++ b/spec/celluloid/io/unix_server_spec.rb @@ -11,7 +11,7 @@ context "inside Celluloid::IO" do it "should be evented" do with_unix_server do |subject| - within_io_actor { Celluloid::IO.evented? }.should be_truthy + expect(within_io_actor { Celluloid::IO.evented? }).to be_truthy end end @@ -19,11 +19,11 @@ with_unix_server do |subject| thread = Thread.new { UNIXSocket.new(example_unix_sock) } peer = within_io_actor { subject.accept } - peer.should be_a Celluloid::IO::UNIXSocket + expect(peer).to be_a Celluloid::IO::UNIXSocket client = thread.value client.write payload - peer.read(payload.size).should eq payload + expect(peer.read(payload.size)).to eq payload end end @@ -40,7 +40,7 @@ context "outside Celluloid::IO" do it "should be blocking" do with_unix_server do |subject| - Celluloid::IO.should_not be_evented + expect(Celluloid::IO).not_to be_evented end end @@ -48,11 +48,11 @@ with_unix_server do |subject| thread = Thread.new { UNIXSocket.new(example_unix_sock) } peer = subject.accept - peer.should be_a Celluloid::IO::UNIXSocket + expect(peer).to be_a Celluloid::IO::UNIXSocket client = thread.value client.write payload - peer.read(payload.size).should eq payload + expect(peer.read(payload.size)).to eq payload end end diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index d568ee0..f102f12 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -15,7 +15,7 @@ peer = thread.value peer << payload - within_io_actor { socket.read(payload.size) }.should eq payload + expect(within_io_actor { socket.read(payload.size) }).to eq payload server.close socket.close @@ -25,56 +25,56 @@ it "should be evented" do with_connected_unix_sockets do |subject| - within_io_actor { Celluloid::IO.evented? }.should be_truthy + expect(within_io_actor { Celluloid::IO.evented? }).to be_truthy end end it "read complete payload when nil size is given to #read" do with_connected_unix_sockets do |subject, peer| peer << payload - within_io_actor { subject.read(nil) }.should eq payload + expect(within_io_actor { subject.read(nil) }).to eq payload end end it "read complete payload when no size is given to #read" do with_connected_unix_sockets do |subject, peer| peer << payload - within_io_actor { subject.read }.should eq payload + expect(within_io_actor { subject.read }).to eq payload end end it "reads data" do with_connected_unix_sockets do |subject, peer| peer << payload - within_io_actor { subject.read(payload.size) }.should eq payload + expect(within_io_actor { subject.read(payload.size) }).to eq payload end end it "reads data in binary encoding" do with_connected_unix_sockets do |subject, peer| peer << payload - within_io_actor { subject.read(payload.size).encoding }.should eq Encoding::BINARY + expect(within_io_actor { subject.read(payload.size).encoding }).to eq Encoding::BINARY end end it "reads partial data" do with_connected_unix_sockets do |subject, peer| peer << payload * 2 - within_io_actor { subject.readpartial(payload.size) }.should eq payload + expect(within_io_actor { subject.readpartial(payload.size) }).to eq payload end end it "reads partial data in binary encoding" do with_connected_unix_sockets do |subject, peer| peer << payload * 2 - within_io_actor { subject.readpartial(payload.size).encoding }.should eq Encoding::BINARY + expect(within_io_actor { subject.readpartial(payload.size).encoding }).to eq Encoding::BINARY end end it "writes data" do with_connected_unix_sockets do |subject, peer| within_io_actor { subject << payload } - peer.read(payload.size).should eq payload + expect(peer.read(payload.size)).to eq payload end end @@ -99,7 +99,7 @@ started_at = Time.now Thread.new{ sleep 0.5; peer.close; } within_io_actor { subject.eof? } - (Time.now - started_at).should > 0.5 + expect(Time.now - started_at).to be > 0.5 end end @@ -111,7 +111,7 @@ within_io_actor { subject.read(1) Celluloid.timeout(0.5) { - subject.eof?.should be_false + expect(subject.eof?).to be_falsey } } }.to raise_error(Celluloid::Task::TimeoutError) @@ -128,7 +128,7 @@ peer = thread.value peer << payload - socket.read(payload.size).should eq payload + expect(socket.read(payload.size)).to eq payload server.close socket.close @@ -138,28 +138,28 @@ it "should be blocking" do with_connected_unix_sockets do |subject| - Celluloid::IO.should_not be_evented + expect(Celluloid::IO).not_to be_evented end end it "reads data" do with_connected_unix_sockets do |subject, peer| peer << payload - subject.read(payload.size).should eq payload + expect(subject.read(payload.size)).to eq payload end end it "reads partial data" do with_connected_unix_sockets do |subject, peer| peer << payload * 2 - subject.readpartial(payload.size).should eq payload + expect(subject.readpartial(payload.size)).to eq payload end end it "writes data" do with_connected_unix_sockets do |subject, peer| subject << payload - peer.read(payload.size).should eq payload + expect(peer.read(payload.size)).to eq payload end end end From ba33f020f1c16696bcf3f14ad5ffe3bb64f03f81 Mon Sep 17 00:00:00 2001 From: //de Date: Thu, 7 May 2015 23:38:24 -0700 Subject: [PATCH 56/97] add .env-* files --- .env-ci | 4 ++++ .env-dev | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 .env-ci create mode 100644 .env-dev diff --git a/.env-ci b/.env-ci new file mode 100644 index 0000000..04573e7 --- /dev/null +++ b/.env-ci @@ -0,0 +1,4 @@ +CELLULOID_SPECS_LOG_STRATEGY=stderr +CELLULOID_SPECS_LOG_LEVEL=3 +CELLULOID_SPECS_LOG_FILE=log/ci.log +CELLULOID_SPECS_LOG_SYNC=false diff --git a/.env-dev b/.env-dev new file mode 100644 index 0000000..91e6111 --- /dev/null +++ b/.env-dev @@ -0,0 +1,4 @@ +CELLULOID_SPECS_LOG_STRATEGY=single +CELLULOID_SPECS_LOG_FILE=log/test.log +CELLULOID_SPECS_LOG_LEVEL=0 +CELLULOID_SPECS_LOG_SYNC=true From 2a9ca9fae7a3907fcdcde82b49828fdb43b9fb32 Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 8 May 2015 01:15:26 -0700 Subject: [PATCH 57/97] remove deadlocking tests under jRuby --- spec/celluloid/io/ssl_socket_spec.rb | 10 ++++++++-- spec/celluloid/io/unix_server_spec.rb | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/spec/celluloid/io/ssl_socket_spec.rb b/spec/celluloid/io/ssl_socket_spec.rb index 81761e9..942a4fd 100644 --- a/spec/celluloid/io/ssl_socket_spec.rb +++ b/spec/celluloid/io/ssl_socket_spec.rb @@ -81,7 +81,10 @@ end it "starts SSL on a connected TCP socket" do - pending "JRuby support" if RUBY_PLATFORM == 'java' + if RUBY_PLATFORM == 'java' + pending "JRuby support" + fail "Bypassing potential deadlock." + end with_raw_sockets do |client, peer| within_io_actor do peer << request @@ -118,7 +121,10 @@ end it "starts SSL on a connected TCP socket" do - pending "JRuby support" if RUBY_PLATFORM == 'java' + if RUBY_PLATFORM == 'java' + pending "JRuby support" + fail "Bypassing potential deadlock." + end with_raw_sockets do |client, peer| peer << request expect(client.read(request.size)).to eq(request) diff --git a/spec/celluloid/io/unix_server_spec.rb b/spec/celluloid/io/unix_server_spec.rb index 6484c8b..b2433f0 100644 --- a/spec/celluloid/io/unix_server_spec.rb +++ b/spec/celluloid/io/unix_server_spec.rb @@ -2,6 +2,7 @@ describe Celluloid::IO::UNIXServer do describe "#accept" do + before do pending "JRuby support" if RUBY_PLATFORM == 'java' end From 30b7ee6abb402f4843cededdacf57b5ecd0343a3 Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 8 May 2015 14:12:38 -0700 Subject: [PATCH 58/97] randomize example socket, and use C::IO::TCPSo --- spec/spec_helper.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1e47ac7..b7f6574 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -35,7 +35,7 @@ def wrap end end -EXAMPLE_PORT = 12345 +EXAMPLE_PORT = 12345 + Random.rand(1024) def example_addr; '127.0.0.1'; end def example_port; EXAMPLE_PORT; end @@ -72,8 +72,7 @@ def with_unix_server def with_connected_sockets with_tcp_server do |server| - # FIXME: client isn't actually a Celluloid::IO::TCPSocket yet - client = ::TCPSocket.new(example_addr, example_port) + client = Celluloid::IO::TCPSocket.new(example_addr, example_port) peer = server.accept begin From ed97b9fa68491f9f140c56454677f90028511c2e Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 8 May 2015 14:16:08 -0700 Subject: [PATCH 59/97] test viable jruby aware units --- spec/celluloid/io/unix_server_spec.rb | 10 ++++++---- spec/celluloid/io/unix_socket_spec.rb | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/spec/celluloid/io/unix_server_spec.rb b/spec/celluloid/io/unix_server_spec.rb index b2433f0..435d3fa 100644 --- a/spec/celluloid/io/unix_server_spec.rb +++ b/spec/celluloid/io/unix_server_spec.rb @@ -1,11 +1,13 @@ require 'spec_helper' describe Celluloid::IO::UNIXServer do - describe "#accept" do - before do - pending "JRuby support" if RUBY_PLATFORM == 'java' - end + before(:each) do + pending "jRuby support" if RUBY_PLATFORM == 'java' + fail "Avoid potential deadlock under jRuby" + end + + describe "#accept" do let(:payload) { 'ohai' } diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index f102f12..58933c3 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -1,8 +1,9 @@ require 'spec_helper' describe Celluloid::IO::UNIXSocket do - before do - pending "JRuby support" if RUBY_PLATFORM == 'java' + before(:each) do + pending "jRuby support" if RUBY_PLATFORM == 'java' + fail "Avoid potential deadlock under jRuby" end let(:payload) { 'ohai' } From 8e73b60320c3f5f0f23091f97edd31bfa4ba644c Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 8 May 2015 15:08:10 -0700 Subject: [PATCH 60/97] only pending on jRuby --- spec/celluloid/io/unix_server_spec.rb | 8 +++++--- spec/celluloid/io/unix_socket_spec.rb | 9 ++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/spec/celluloid/io/unix_server_spec.rb b/spec/celluloid/io/unix_server_spec.rb index 435d3fa..d08ec4e 100644 --- a/spec/celluloid/io/unix_server_spec.rb +++ b/spec/celluloid/io/unix_server_spec.rb @@ -2,9 +2,11 @@ describe Celluloid::IO::UNIXServer do - before(:each) do - pending "jRuby support" if RUBY_PLATFORM == 'java' - fail "Avoid potential deadlock under jRuby" + if RUBY_PLATFORM == 'java' + before(:each) do + pending "jRuby support" + fail "Avoid potential deadlock under jRuby" + end end describe "#accept" do diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index 58933c3..6981833 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -1,9 +1,12 @@ require 'spec_helper' describe Celluloid::IO::UNIXSocket do - before(:each) do - pending "jRuby support" if RUBY_PLATFORM == 'java' - fail "Avoid potential deadlock under jRuby" + + if RUBY_PLATFORM == 'java' + before(:each) do + pending "jRuby support" + fail "Avoid potential deadlock under jRuby" + end end let(:payload) { 'ohai' } From 6b10fb34ac5bb4467ca0eb2de8c2f0ecd185c521 Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 8 May 2015 15:16:35 -0700 Subject: [PATCH 61/97] use fast finish --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a393baa..c719fc8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ rvm: # For right now the imporant thing is to test BACKPORTED mode: matrix: + fast_finish: true allow_failures: - rvm: rbx-2 - rvm: ruby-head From 496e87ca9ba9fb9aa061b380c4de2ae27d1f5eba Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 8 May 2015 22:10:10 -0700 Subject: [PATCH 62/97] bump version and recut --- culture | 2 +- lib/celluloid/io/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/culture b/culture index 005c416..2b3772a 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit 005c4165a16c1af12422849576bbc5bb60e17673 +Subproject commit 2b3772a275150ea28c3f5e1031abd81a38881d77 diff --git a/lib/celluloid/io/version.rb b/lib/celluloid/io/version.rb index 1416384..634306f 100644 --- a/lib/celluloid/io/version.rb +++ b/lib/celluloid/io/version.rb @@ -1,5 +1,5 @@ module Celluloid module IO - VERSION = "0.16.5" + VERSION = "0.16.5.pre0" end end From ba3cbf632a711785c745764116831c6a14f4d09d Mon Sep 17 00:00:00 2001 From: Leo Correa Date: Thu, 4 Jun 2015 15:10:11 -0400 Subject: [PATCH 63/97] Fix typo in gets documentation --- lib/celluloid/io/stream.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/celluloid/io/stream.rb b/lib/celluloid/io/stream.rb index 8817974..9921b6d 100644 --- a/lib/celluloid/io/stream.rb +++ b/lib/celluloid/io/stream.rb @@ -142,7 +142,7 @@ def readpartial(maxlen, buf=nil) ret end - # Reads the next "line+ from the stream. Lines are separated by +eol+. If + # Reads the next line from the stream. Lines are separated by +eol+. If # +limit+ is provided the result will not be longer than the given number of # bytes. # From 625aa2a41ba66c376f80a47f4449808dbbfcb113 Mon Sep 17 00:00:00 2001 From: //de Date: Sat, 4 Jul 2015 04:15:47 -0700 Subject: [PATCH 64/97] removed duplicate dependency pulled in by Celluloid::Culture, and add project co-owner --- celluloid-io.gemspec | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index 72a11fd..3b54713 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -5,8 +5,8 @@ Gem::Specification.new do |gem| gem.name = "celluloid-io" gem.version = Celluloid::IO::VERSION gem.license = 'MIT' - gem.authors = ["Tony Arcieri"] - gem.email = ["tony.arcieri@gmail.com"] + gem.authors = ["Tony Arcieri", "digitalextremist //"] + gem.email = ["tony.arcieri@gmail.com", "code@extremist.digital"] gem.description = "Evented IO for Celluloid actors" gem.summary = "Celluloid::IO allows you to monitor multiple IO objects within a Celluloid actor" gem.homepage = "http://github.com/celluloid/celluloid-io" @@ -20,6 +20,5 @@ Gem::Specification.new do |gem| gem.add_dependency 'nio4r', '>= 1.1.0' - gem.add_development_dependency 'guard-rspec' gem.add_development_dependency 'rb-fsevent', '~> 0.9.1' if RUBY_PLATFORM =~ /darwin/ end From e84e3dc0c79d84857571dc044c807209db269390 Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 7 Aug 2015 11:38:57 -0700 Subject: [PATCH 65/97] more support for celluloid/celluloid#424 --- celluloid-io.gemspec | 2 +- culture | 2 +- spec/celluloid/io/reactor_spec.rb | 4 ++-- spec/celluloid/io/tcp_socket_spec.rb | 2 +- spec/celluloid/io/unix_socket_spec.rb | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index 3b54713..e031399 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -5,7 +5,7 @@ Gem::Specification.new do |gem| gem.name = "celluloid-io" gem.version = Celluloid::IO::VERSION gem.license = 'MIT' - gem.authors = ["Tony Arcieri", "digitalextremist //"] + gem.authors = ["Tony Arcieri", "Donovan Keme"] gem.email = ["tony.arcieri@gmail.com", "code@extremist.digital"] gem.description = "Evented IO for Celluloid actors" gem.summary = "Celluloid::IO allows you to monitor multiple IO objects within a Celluloid actor" diff --git a/culture b/culture index 2b3772a..7f0689b 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit 2b3772a275150ea28c3f5e1031abd81a38881d77 +Subproject commit 7f0689b2ddcc3e6ba563171d6b3d754d46996644 diff --git a/spec/celluloid/io/reactor_spec.rb b/spec/celluloid/io/reactor_spec.rb index f552683..036b69c 100644 --- a/spec/celluloid/io/reactor_spec.rb +++ b/spec/celluloid/io/reactor_spec.rb @@ -21,8 +21,8 @@ socket.readpartial(2046) end end - # rescuing timeout, ok. rescuing terminated error, is it ok? TODO: investigate - rescue Celluloid::Task::TerminatedError, Timeout::Error + # rescuing timeout, ok. rescuing terminated exception, is it ok? TODO: investigate + rescue Celluloid::TaskTerminated, Celluloid::TaskTimeout, Timeout::Error ensure socket.readpartial(2046) handle = true diff --git a/spec/celluloid/io/tcp_socket_spec.rb b/spec/celluloid/io/tcp_socket_spec.rb index d94f0eb..9c0eec3 100644 --- a/spec/celluloid/io/tcp_socket_spec.rb +++ b/spec/celluloid/io/tcp_socket_spec.rb @@ -127,7 +127,7 @@ expect(subject.eof?).to be_falsey } } - }.to raise_error(Celluloid::Task::TimeoutError) + }.to raise_error(Celluloid::TaskTimeout) end end end diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index 6981833..5b80ab8 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -118,7 +118,7 @@ expect(subject.eof?).to be_falsey } } - }.to raise_error(Celluloid::Task::TimeoutError) + }.to raise_error(Celluloid::TaskTimeout) end end end From 5eaee1646b7513b6ef417d3a6b8536c4618d3b90 Mon Sep 17 00:00:00 2001 From: //de Date: Fri, 7 Aug 2015 11:41:44 -0700 Subject: [PATCH 66/97] sync version to Celluloid and Celluloid::ZMQ, add rbx-2 requirement --- .travis.yml | 1 - lib/celluloid/io/version.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c719fc8..e8ad3dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,6 @@ rvm: matrix: fast_finish: true allow_failures: - - rvm: rbx-2 - rvm: ruby-head - rvm: jruby-head - env: CELLULOID_BACKPORTED=true diff --git a/lib/celluloid/io/version.rb b/lib/celluloid/io/version.rb index 634306f..b3b65cc 100644 --- a/lib/celluloid/io/version.rb +++ b/lib/celluloid/io/version.rb @@ -1,5 +1,5 @@ module Celluloid module IO - VERSION = "0.16.5.pre0" + VERSION = "0.17.0" end end From dc352d5a4d86684ad7cc8bc3b348ee7e9d92f8b3 Mon Sep 17 00:00:00 2001 From: //de Date: Sat, 8 Aug 2015 22:14:57 -0700 Subject: [PATCH 67/97] sleep long enough to let TCP Server spin up with SSL Server in tests. make damn sure the port is available before assigning it. assign a different port for every test. translate the jRuby UNIX Socket exception to EADDRINUSE --- Gemfile | 3 ++ celluloid-io.gemspec | 2 +- culture | 2 +- lib/celluloid/io/unix_server.rb | 12 +++++- spec/celluloid/io/reactor_spec.rb | 1 + spec/celluloid/io/ssl_server_spec.rb | 23 ++++++------ spec/celluloid/io/ssl_socket_spec.rb | 53 ++++++++++++++++++--------- spec/celluloid/io/tcp_server_spec.rb | 9 +++-- spec/celluloid/io/tcp_socket_spec.rb | 35 +++++++++--------- spec/celluloid/io/udp_socket_spec.rb | 1 + spec/celluloid/io/unix_server_spec.rb | 9 +---- spec/celluloid/io/unix_socket_spec.rb | 5 ++- spec/spec_helper.rb | 43 +++++++++++++++++----- 13 files changed, 126 insertions(+), 72 deletions(-) diff --git a/Gemfile b/Gemfile index 2e4054c..9911034 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,5 @@ require File.expand_path("../culture/sync", __FILE__) + Celluloid::Sync::Gemfile[self] + +gem 'nio4r', github: 'celluloid/nio4r', branch: 'master' diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index e031399..e5a231c 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |gem| Celluloid::Sync::Gemspec[gem] - gem.add_dependency 'nio4r', '>= 1.1.0' + gem.add_dependency 'nio4r', '>= 1.1' gem.add_development_dependency 'rb-fsevent', '~> 0.9.1' if RUBY_PLATFORM =~ /darwin/ end diff --git a/culture b/culture index 7f0689b..5f92523 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit 7f0689b2ddcc3e6ba563171d6b3d754d46996644 +Subproject commit 5f925237663e18fd6931444dc6f8378264a238d6 diff --git a/lib/celluloid/io/unix_server.rb b/lib/celluloid/io/unix_server.rb index f658d0f..53b71cf 100644 --- a/lib/celluloid/io/unix_server.rb +++ b/lib/celluloid/io/unix_server.rb @@ -12,7 +12,17 @@ def self.open(socket_path) end def initialize(socket_path) - @server = ::UNIXServer.new(socket_path) + begin + @server = ::UNIXServer.new(socket_path) + rescue => ex + # Translate the EADDRINUSE jRuby exception. + raise unless RUBY_PLATFORM == 'java' + if ex.class.name == "IOError" && # Won't agree to .is_a?(IOError) + ex.message.include?("in use") + raise Errno::EADDRINUSE.new(ex.message) + end + raise + end end def accept diff --git a/spec/celluloid/io/reactor_spec.rb b/spec/celluloid/io/reactor_spec.rb index 036b69c..bc12c6c 100644 --- a/spec/celluloid/io/reactor_spec.rb +++ b/spec/celluloid/io/reactor_spec.rb @@ -2,6 +2,7 @@ describe Celluloid::IO::Reactor do let(:payload) { "balls" } + let(:example_port) { assign_port } it "shouldn't crash" do server = ::TCPServer.new example_addr, example_port diff --git a/spec/celluloid/io/ssl_server_spec.rb b/spec/celluloid/io/ssl_server_spec.rb index 04cb820..6d6d3a7 100644 --- a/spec/celluloid/io/ssl_server_spec.rb +++ b/spec/celluloid/io/ssl_server_spec.rb @@ -9,7 +9,8 @@ context.key = client_key end end - + + let(:example_port) { assign_port } let(:server_cert) { OpenSSL::X509::Certificate.new fixture_dir.join("server.crt").read } let(:server_key) { OpenSSL::PKey::RSA.new fixture_dir.join("server.key").read } let(:server_context) do @@ -24,15 +25,15 @@ context "inside Celluloid::IO" do it "should be evented" do - with_ssl_server do |subject| + with_ssl_server(example_port) do |subject| expect(within_io_actor { Celluloid::IO.evented? }).to be_truthy end end it "accepts a connection and returns a Celluloid::IO::SSLSocket" do - with_ssl_server do |subject| + with_ssl_server(example_port) do |subject| thread = Thread.new do - raw = TCPSocket.new(example_addr, example_ssl_port) + raw = TCPSocket.new(example_addr, example_port) OpenSSL::SSL::SSLSocket.new(raw, client_context).connect end peer = within_io_actor { subject.accept } @@ -47,15 +48,15 @@ context "outside Celluloid::IO" do it "should be blocking" do - with_ssl_server do |subject| + with_ssl_server(example_port) do |subject| expect(Celluloid::IO).not_to be_evented end end it "accepts a connection and returns a Celluloid::IO::SSLSocket" do - with_ssl_server do |subject| + with_ssl_server(example_port) do |subject| thread = Thread.new do - raw = TCPSocket.new(example_addr, example_ssl_port) + raw = TCPSocket.new(example_addr, example_port) OpenSSL::SSL::SSLSocket.new(raw, client_context).connect end peer = subject.accept @@ -71,15 +72,15 @@ describe "#initialize" do it "should auto-wrap a raw ::TCPServer" do - raw_server = ::TCPServer.new(example_addr, example_ssl_port) - with_ssl_server(raw_server) do |ssl_server| + raw_server = ::TCPServer.new(example_addr, example_port) + with_ssl_server(example_port, raw_server) do |ssl_server| expect(ssl_server.tcp_server.class).to eq(Celluloid::IO::TCPServer) end end end - def with_ssl_server(raw_server = nil) - raw_server ||= Celluloid::IO::TCPServer.new(example_addr, example_ssl_port) + def with_ssl_server(port, raw_server = nil) + raw_server ||= Celluloid::IO::TCPServer.new(example_addr, port) server = Celluloid::IO::SSLServer.new(raw_server, server_context) begin yield server diff --git a/spec/celluloid/io/ssl_socket_spec.rb b/spec/celluloid/io/ssl_socket_spec.rb index 942a4fd..5ec62be 100644 --- a/spec/celluloid/io/ssl_socket_spec.rb +++ b/spec/celluloid/io/ssl_socket_spec.rb @@ -5,6 +5,7 @@ let(:request) { 'ping' } let(:response) { 'pong' } + let(:example_port) { assign_port } let(:client_cert) { OpenSSL::X509::Certificate.new fixture_dir.join("client.crt").read } let(:client_key) { OpenSSL::PKey::RSA.new fixture_dir.join("client.key").read } let(:client_context) do @@ -14,21 +15,33 @@ end end - let(:client) do - remaining_attempts = 3 - - begin - TCPSocket.new example_addr, example_ssl_port - rescue Errno::ECONNREFUSED - # HAX: sometimes this fails to connect? o_O - # This is quite likely due to the Thread.pass style spinlocks for startup - raise if remaining_attempts < 1 - remaining_attempts -= 1 + after(:each) { + client.close rescue nil + server.close rescue nil + } - # Seems gimpy, but sleep and retry - sleep 0.1 - retry + let(:client) do + attempts = 0 + socket = begin + Timeout.timeout(MAX_TIME) { + begin + TCPSocket.new example_addr, example_port + rescue Errno::ECONNREFUSED + raise if attempts >= MAX_ATTEMPTS + attempts += 1 + # HAX: sometimes this fails to connect? o_O + # ... This can often fail 20 times in a row ... so yeah + # This is quite likely due to the Thread.pass style spinlocks for startup + # Seems gimpy, but sleep and retry + sleep 0.0126 + retry + end + } + rescue => ex + attempted = "Tried #{attempts} times to instantiate socket." + raise ex.class.new(attempted) end + return socket end let(:ssl_client) { Celluloid::IO::SSLSocket.new client, client_context } @@ -42,21 +55,23 @@ end end - let(:server) { TCPServer.new example_addr, example_ssl_port } - let(:ssl_server) { OpenSSL::SSL::SSLServer.new server, server_context } + let(:server) { TCPServer.new example_addr, example_port } + let(:ssl_server) { OpenSSL::SSL::SSLServer.new(server, server_context) } let(:server_thread) do - Thread.new { ssl_server.accept }.tap do |thread| + server = Thread.new { ssl_server.accept }.tap do |thread| Thread.pass while thread.status && thread.status != "sleep" thread.join unless thread.status end + server end - let(:celluloid_server) { Celluloid::IO::TCPServer.new example_addr, example_ssl_port } + let(:celluloid_server) { Celluloid::IO::TCPServer.new example_addr, example_port } let(:raw_server_thread) do - Thread.new { celluloid_server.accept }.tap do |thread| + server = Thread.new { celluloid_server.accept }.tap do |thread| Thread.pass while thread.status && thread.status != "sleep" thread.join unless thread.status end + server end context "duck typing ::SSLSocket" do @@ -195,6 +210,7 @@ def with_ssl_sockets server_thread + sleep 0.222 # Needs time to spin up, or will throw out Errno::ECONNECTREFUSED to client. ssl_client.connect begin @@ -210,6 +226,7 @@ def with_ssl_sockets def with_raw_sockets raw_server_thread + sleep 0.222 # Needs time to spin up, or will throw out Errno::ECONNECTREFUSED to client. client begin diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index 038cf8f..633d326 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -3,6 +3,7 @@ describe Celluloid::IO::TCPServer do describe "#accept" do let(:payload) { 'ohai' } + let(:example_port) { assign_port } it "can be initialized without a host" do expect { Celluloid::IO::TCPServer.new(2000).close }.to_not raise_error @@ -10,13 +11,13 @@ context "inside Celluloid::IO" do it "should be evented" do - with_tcp_server do |subject| + with_tcp_server(example_port) do |subject| expect(within_io_actor { Celluloid::IO.evented? }).to be_truthy end end it "accepts a connection and returns a Celluloid::IO::TCPSocket" do - with_tcp_server do |subject| + with_tcp_server(example_port) do |subject| thread = Thread.new { TCPSocket.new(example_addr, example_port) } peer = within_io_actor { subject.accept } expect(peer).to be_a Celluloid::IO::TCPSocket @@ -29,13 +30,13 @@ context "outside Celluloid::IO" do it "should be blocking" do - with_tcp_server do |subject| + with_tcp_server(example_port) do |subject| expect(Celluloid::IO).not_to be_evented end end it "accepts a connection and returns a Celluloid::IO::TCPSocket" do - with_tcp_server do |subject| + with_tcp_server(example_port) do |subject| thread = Thread.new { TCPSocket.new(example_addr, example_port) } peer = subject.accept expect(peer).to be_a Celluloid::IO::TCPSocket diff --git a/spec/celluloid/io/tcp_socket_spec.rb b/spec/celluloid/io/tcp_socket_spec.rb index 9c0eec3..fa5a24c 100644 --- a/spec/celluloid/io/tcp_socket_spec.rb +++ b/spec/celluloid/io/tcp_socket_spec.rb @@ -2,6 +2,7 @@ describe Celluloid::IO::TCPSocket do let(:payload) { 'ohai' } + let(:example_port) { assign_port } context "inside Celluloid::IO" do @@ -46,55 +47,55 @@ end it "should be evented" do - with_connected_sockets do |subject| + with_connected_sockets(example_port) do |subject| expect(within_io_actor { Celluloid::IO.evented? }).to be_truthy end end it "read complete payload when nil size is given to #read" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer << payload expect(within_io_actor { subject.read(nil) }).to eq payload end end it "read complete payload when no size is given to #read" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer << payload expect(within_io_actor { subject.read }).to eq payload end end it "reads data" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer << payload expect(within_io_actor { subject.read(payload.size) }).to eq payload end end it "reads data in binary encoding" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer << payload expect(within_io_actor { subject.read(payload.size).encoding }).to eq Encoding::BINARY end end it "reads partial data" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer << payload * 2 expect(within_io_actor { subject.readpartial(payload.size) }).to eq payload end end it "reads partial data in binary encoding" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer << payload * 2 expect(within_io_actor { subject.readpartial(payload.size).encoding }).to eq Encoding::BINARY end end it "writes data" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| within_io_actor { subject << payload } expect(peer.read(payload.size)).to eq payload end @@ -108,7 +109,7 @@ context 'eof?' do it "blocks actor then returns by close" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| started_at = Time.now Thread.new{ sleep 0.5; peer.close; } within_io_actor { subject.eof? } @@ -117,7 +118,7 @@ end it "blocks until gets the next byte" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer << 0x00 peer.flush expect { @@ -134,7 +135,7 @@ context "readpartial" do it "raises EOFError when reading from a closed socket" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer.close expect { within_io_actor { subject.readpartial(payload.size) } @@ -145,7 +146,7 @@ it "raises IOError when active sockets are closed across threads" do pending "not implemented" - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| actor = ExampleActor.new begin read_future = actor.future.wrap do @@ -162,7 +163,7 @@ it "raises IOError when partial reading from a socket the peer closed" do pending "async block running on receiver" - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| actor = ExampleActor.new begin actor.async.wrap { sleep 0.01; peer.close } @@ -193,27 +194,27 @@ end it "should be blocking" do - with_connected_sockets do |subject| + with_connected_sockets(example_port) do |subject| expect(Celluloid::IO).not_to be_evented end end it "reads data" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer << payload expect(subject.read(payload.size)).to eq payload end end it "reads partial data" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer << payload * 2 expect(subject.readpartial(payload.size)).to eq payload end end it "writes data" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| subject << payload expect(peer.read(payload.size)).to eq payload end diff --git a/spec/celluloid/io/udp_socket_spec.rb b/spec/celluloid/io/udp_socket_spec.rb index 17c95a3..7433fd2 100644 --- a/spec/celluloid/io/udp_socket_spec.rb +++ b/spec/celluloid/io/udp_socket_spec.rb @@ -2,6 +2,7 @@ describe Celluloid::IO::UDPSocket do let(:payload) { 'ohai' } + let(:example_port) { assign_port } subject do Celluloid::IO::UDPSocket.new.tap do |sock| sock.bind example_addr, example_port diff --git a/spec/celluloid/io/unix_server_spec.rb b/spec/celluloid/io/unix_server_spec.rb index d08ec4e..5b631cc 100644 --- a/spec/celluloid/io/unix_server_spec.rb +++ b/spec/celluloid/io/unix_server_spec.rb @@ -1,13 +1,7 @@ require 'spec_helper' describe Celluloid::IO::UNIXServer do - - if RUBY_PLATFORM == 'java' - before(:each) do - pending "jRuby support" - fail "Avoid potential deadlock under jRuby" - end - end + let(:example_port) { assign_port } describe "#accept" do @@ -21,6 +15,7 @@ end it "accepts a connection and returns a Celluloid::IO::UNIXSocket" do + pending if RUBY_PLATFORM == 'java' with_unix_server do |subject| thread = Thread.new { UNIXSocket.new(example_unix_sock) } peer = within_io_actor { subject.accept } diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index 5b80ab8..dbae9cf 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -10,6 +10,7 @@ end let(:payload) { 'ohai' } + let(:example_port) { assign_port } context "inside Celluloid::IO" do it "connects to UNIX servers" do @@ -99,7 +100,7 @@ context 'eof?' do it "blocks actor then returns by close" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| started_at = Time.now Thread.new{ sleep 0.5; peer.close; } within_io_actor { subject.eof? } @@ -108,7 +109,7 @@ end it "blocks until gets the next byte" do - with_connected_sockets do |subject, peer| + with_connected_sockets(example_port) do |subject, peer| peer << 0x00 peer.flush expect { diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b7f6574..a0915e0 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,8 +3,12 @@ require 'celluloid/io' require 'celluloid/rspec' require 'coveralls' + Coveralls.wear! +MAX_TIME = 7 +MAX_ATTEMPTS = 20 + logfile = File.open(File.expand_path("../../log/test.log", __FILE__), 'a') logfile.sync = true @@ -16,12 +20,16 @@ config.filter_run :focus => true config.run_all_when_everything_filtered = true + config.around(:each) { |example| + Timeout.timeout(MAX_TIME) { + example.run + } + } + config.before do Celluloid.logger = logger Celluloid.shutdown - Celluloid.boot - FileUtils.rm("/tmp/cell_sock") if File.exist?("/tmp/cell_sock") end end @@ -35,12 +43,27 @@ def wrap end end -EXAMPLE_PORT = 12345 + Random.rand(1024) +# Would use Addrinfo(addr,0) but the class is missing/unstable on RBX. +def assign_port + port = 12000 + Random.rand(1024) + attempts = 0 + begin + socket = ::TCPServer.new(example_addr, port) + rescue Errno::ECONNREFUSED, Errno::EADDRINUSE => ex + raise ex.class.new("Tried #{attempts} times to assign port.") unless attempts < MAX_ATTEMPTS + attempts += 1 + port += 1 + socket.close rescue nil + sleep 0.126 + retry + end + return port +ensure + socket.close rescue nil +end def example_addr; '127.0.0.1'; end -def example_port; EXAMPLE_PORT; end def example_unix_sock; '/tmp/cell_sock'; end -def example_ssl_port; EXAMPLE_PORT + 1; end def fixture_dir; Pathname.new File.expand_path("../fixtures", __FILE__); end @@ -51,8 +74,8 @@ def within_io_actor(&block) actor.terminate if actor.alive? end -def with_tcp_server - server = Celluloid::IO::TCPServer.new(example_addr, example_port) +def with_tcp_server(port) + server = Celluloid::IO::TCPServer.new(example_addr, port) begin yield server ensure @@ -70,9 +93,9 @@ def with_unix_server end end -def with_connected_sockets - with_tcp_server do |server| - client = Celluloid::IO::TCPSocket.new(example_addr, example_port) +def with_connected_sockets(port) + with_tcp_server(port) do |server| + client = Celluloid::IO::TCPSocket.new(example_addr, port) peer = server.accept begin From 9305de7e46ed0b29e5dd144985b659abb9db05d2 Mon Sep 17 00:00:00 2001 From: //de Date: Sat, 8 Aug 2015 22:23:24 -0700 Subject: [PATCH 68/97] remove ni04r from gemfile, that was for testing only --- Gemfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Gemfile b/Gemfile index 9911034..58da518 100644 --- a/Gemfile +++ b/Gemfile @@ -2,4 +2,3 @@ require File.expand_path("../culture/sync", __FILE__) Celluloid::Sync::Gemfile[self] -gem 'nio4r', github: 'celluloid/nio4r', branch: 'master' From e8c84bda9ff12e31ca43acd0c97ff89a126f5fe0 Mon Sep 17 00:00:00 2001 From: //de Date: Sat, 8 Aug 2015 22:38:49 -0700 Subject: [PATCH 69/97] add alternate resolver to try and get IPv4 as expected --- lib/celluloid/io/dns_resolver.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/celluloid/io/dns_resolver.rb b/lib/celluloid/io/dns_resolver.rb index be0ef5e..8bebec5 100644 --- a/lib/celluloid/io/dns_resolver.rb +++ b/lib/celluloid/io/dns_resolver.rb @@ -77,7 +77,7 @@ def build_query(hostname) end def resolve_host(host) - resolve_ip(Resolv::IPv4, host) || resolve_ip(Resolv::IPv6, host) + resolve_ip(Resolv::IPv4, host) || get_address(host) || resolve_ip(Resolv::IPv6, host) end def resolve_ip(klass, host) @@ -86,6 +86,13 @@ def resolve_ip(klass, host) rescue ArgumentError end end + + private + + def get_address(host) + Resolv::Hosts.new(host).get_address. + rescue + end end end end From f2c11f53278a83843d301ad229b6b3cb9b1c0d81 Mon Sep 17 00:00:00 2001 From: //de Date: Mon, 24 Aug 2015 16:38:30 -0700 Subject: [PATCH 70/97] take in new dependencies from celluloid-culture --- culture | 2 +- lib/celluloid/io/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/culture b/culture index 5f92523..d16115e 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit 5f925237663e18fd6931444dc6f8378264a238d6 +Subproject commit d16115ec958c6b17aed2edde22f57cfc3ca91d34 diff --git a/lib/celluloid/io/version.rb b/lib/celluloid/io/version.rb index b3b65cc..46be987 100644 --- a/lib/celluloid/io/version.rb +++ b/lib/celluloid/io/version.rb @@ -1,5 +1,5 @@ module Celluloid module IO - VERSION = "0.17.0" + VERSION = "0.17.1" end end From ffe9c6317c468819308e0a7955967e1d19c89e2f Mon Sep 17 00:00:00 2001 From: //de Date: Tue, 22 Sep 2015 14:23:15 -0700 Subject: [PATCH 71/97] change name of benchmarking actor and mark for refactoring --- benchmarks/actor.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/benchmarks/actor.rb b/benchmarks/actor.rb index 4a9a679..a8e16e3 100755 --- a/benchmarks/actor.rb +++ b/benchmarks/actor.rb @@ -5,7 +5,8 @@ require 'celluloid/io' require 'benchmark/ips' -class ExampleActor +#de TODO: Consolidate with Celluloid benchmarking actor. +class BenchmarkingActor include Celluloid::IO def initialize @@ -23,7 +24,7 @@ def wait_until_finished end end -example_actor = ExampleActor.new +example_actor = BenchmarkingActor.new mailbox = Celluloid::IO::Mailbox.new latch_in, latch_out = Queue.new, Queue.new @@ -36,7 +37,7 @@ def wait_until_finished end Benchmark.ips do |ips| - ips.report("spawn") { ExampleActor.new.terminate } + ips.report("spawn") { BenchmarkingActor.new.terminate } ips.report("calls") { example_actor.example_method } From 52e563a7ba59cc049ddeb37d1f08c4d94da0902f Mon Sep 17 00:00:00 2001 From: //de Date: Tue, 22 Sep 2015 14:44:11 -0700 Subject: [PATCH 72/97] preparing consolidation of tests for celluloid/culture#31 --- culture | 2 +- spec/celluloid/io/ssl_socket_spec.rb | 4 ++-- spec/spec_helper.rb | 16 ++++++---------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/culture b/culture index d16115e..c0ae083 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit d16115ec958c6b17aed2edde22f57cfc3ca91d34 +Subproject commit c0ae083774874f3975cd442eb57627979d0b95fd diff --git a/spec/celluloid/io/ssl_socket_spec.rb b/spec/celluloid/io/ssl_socket_spec.rb index 5ec62be..08eec94 100644 --- a/spec/celluloid/io/ssl_socket_spec.rb +++ b/spec/celluloid/io/ssl_socket_spec.rb @@ -23,11 +23,11 @@ let(:client) do attempts = 0 socket = begin - Timeout.timeout(MAX_TIME) { + Timeout.timeout(Specs::MAX_EXECUTION) { begin TCPSocket.new example_addr, example_port rescue Errno::ECONNREFUSED - raise if attempts >= MAX_ATTEMPTS + raise if attempts >= Specs::MAX_ATTEMPTS attempts += 1 # HAX: sometimes this fails to connect? o_O # ... This can often fail 20 times in a row ... so yeah diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a0915e0..01d9a33 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,14 +1,9 @@ -require 'rubygems' -require 'bundler/setup' -require 'celluloid/io' require 'celluloid/rspec' -require 'coveralls' - -Coveralls.wear! +require 'celluloid/io' -MAX_TIME = 7 -MAX_ATTEMPTS = 20 +Dir[ *Specs::INCLUDE_PATHS ].map { |f| require f } +=begin logfile = File.open(File.expand_path("../../log/test.log", __FILE__), 'a') logfile.sync = true @@ -21,7 +16,7 @@ config.run_all_when_everything_filtered = true config.around(:each) { |example| - Timeout.timeout(MAX_TIME) { + Timeout.timeout(Specs::MAX_EXECUTION) { example.run } } @@ -33,6 +28,7 @@ FileUtils.rm("/tmp/cell_sock") if File.exist?("/tmp/cell_sock") end end +=end class ExampleActor include Celluloid::IO @@ -50,7 +46,7 @@ def assign_port begin socket = ::TCPServer.new(example_addr, port) rescue Errno::ECONNREFUSED, Errno::EADDRINUSE => ex - raise ex.class.new("Tried #{attempts} times to assign port.") unless attempts < MAX_ATTEMPTS + raise ex.class.new("Tried #{attempts} times to assign port.") unless attempts < Specs::MAX_ATTEMPTS attempts += 1 port += 1 socket.close rescue nil From 7b262c226babf63191f78cae957a8dc71d358196 Mon Sep 17 00:00:00 2001 From: //de Date: Sat, 26 Sep 2015 21:19:12 -0700 Subject: [PATCH 73/97] resolution of celluloid/culture#31 for Celluloid::IO --- spec/celluloid/io/actor_spec.rb | 2 +- spec/celluloid/io/dns_resolver_spec.rb | 4 +- spec/celluloid/io/mailbox_spec.rb | 2 +- spec/celluloid/io/reactor_spec.rb | 14 +-- spec/celluloid/io/ssl_server_spec.rb | 5 +- spec/celluloid/io/ssl_socket_spec.rb | 2 +- spec/celluloid/io/tcp_server_spec.rb | 4 +- spec/celluloid/io/tcp_socket_spec.rb | 18 ++-- spec/celluloid/io/udp_socket_spec.rb | 2 +- spec/celluloid/io/unix_server_spec.rb | 2 +- spec/celluloid/io/unix_socket_spec.rb | 10 +- spec/celluloid/io_spec.rb | 4 +- spec/spec_helper.rb | 127 ++----------------------- spec/support/examples/classes.rb | 12 +++ spec/support/examples/methods.rb | 83 ++++++++++++++++ 15 files changed, 141 insertions(+), 150 deletions(-) create mode 100644 spec/support/examples/classes.rb create mode 100644 spec/support/examples/methods.rb diff --git a/spec/celluloid/io/actor_spec.rb b/spec/celluloid/io/actor_spec.rb index e72364d..7798b9d 100644 --- a/spec/celluloid/io/actor_spec.rb +++ b/spec/celluloid/io/actor_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -describe Celluloid::IO do +RSpec.describe Celluloid::IO, library: :IO do it_behaves_like "a Celluloid Actor", Celluloid::IO end diff --git a/spec/celluloid/io/dns_resolver_spec.rb b/spec/celluloid/io/dns_resolver_spec.rb index edae36e..8360f43 100644 --- a/spec/celluloid/io/dns_resolver_spec.rb +++ b/spec/celluloid/io/dns_resolver_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -describe Celluloid::IO::DNSResolver do - describe '#resolve' do +RSpec.describe Celluloid::IO::DNSResolver, library: :IO do + context '#resolve' do it 'resolves hostnames statically from hosts file without nameservers' do # /etc/resolv.conf doesn't exist on Mac OSX when no networking is # disabled, thus .nameservers would return nil diff --git a/spec/celluloid/io/mailbox_spec.rb b/spec/celluloid/io/mailbox_spec.rb index 7a6109e..db2abef 100644 --- a/spec/celluloid/io/mailbox_spec.rb +++ b/spec/celluloid/io/mailbox_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -describe Celluloid::IO::Mailbox do +RSpec.describe Celluloid::IO::Mailbox, library: :IO do it_behaves_like "a Celluloid Mailbox" end diff --git a/spec/celluloid/io/reactor_spec.rb b/spec/celluloid/io/reactor_spec.rb index bc12c6c..62fc4eb 100644 --- a/spec/celluloid/io/reactor_spec.rb +++ b/spec/celluloid/io/reactor_spec.rb @@ -1,19 +1,19 @@ require 'spec_helper' -describe Celluloid::IO::Reactor do +RSpec.describe Celluloid::IO::Reactor, library: :IO do let(:payload) { "balls" } let(:example_port) { assign_port } - + it "shouldn't crash" do server = ::TCPServer.new example_addr, example_port - + thread = Thread.new { server.accept } - + socket = within_io_actor { Celluloid::IO::TCPSocket.new example_addr, example_port } peer = thread.value peer_thread = Thread.new { loop { peer << payload } } handle = false - + # Main server body: within_io_actor do begin @@ -29,9 +29,9 @@ handle = true end end - + expect(handle).to be_truthy - + server.close peer.close socket.close diff --git a/spec/celluloid/io/ssl_server_spec.rb b/spec/celluloid/io/ssl_server_spec.rb index 6d6d3a7..18e97b6 100644 --- a/spec/celluloid/io/ssl_server_spec.rb +++ b/spec/celluloid/io/ssl_server_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Celluloid::IO::SSLServer do +RSpec.describe Celluloid::IO::SSLServer, library: :IO do let(:client_cert) { OpenSSL::X509::Certificate.new fixture_dir.join("client.crt").read } let(:client_key) { OpenSSL::PKey::RSA.new fixture_dir.join("client.key").read } let(:client_context) do @@ -9,7 +9,7 @@ context.key = client_key end end - + let(:example_port) { assign_port } let(:server_cert) { OpenSSL::X509::Certificate.new fixture_dir.join("server.crt").read } let(:server_key) { OpenSSL::PKey::RSA.new fixture_dir.join("server.key").read } @@ -89,4 +89,3 @@ def with_ssl_server(port, raw_server = nil) end end end - diff --git a/spec/celluloid/io/ssl_socket_spec.rb b/spec/celluloid/io/ssl_socket_spec.rb index 08eec94..fc87fe7 100644 --- a/spec/celluloid/io/ssl_socket_spec.rb +++ b/spec/celluloid/io/ssl_socket_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' require 'openssl' -describe Celluloid::IO::SSLSocket do +RSpec.describe Celluloid::IO::SSLSocket, library: :IO do let(:request) { 'ping' } let(:response) { 'pong' } diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index 633d326..452e605 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -describe Celluloid::IO::TCPServer do - describe "#accept" do +RSpec.describe Celluloid::IO::TCPServer, library: :IO do + context "#accept" do let(:payload) { 'ohai' } let(:example_port) { assign_port } diff --git a/spec/celluloid/io/tcp_socket_spec.rb b/spec/celluloid/io/tcp_socket_spec.rb index fa5a24c..9500012 100644 --- a/spec/celluloid/io/tcp_socket_spec.rb +++ b/spec/celluloid/io/tcp_socket_spec.rb @@ -1,8 +1,9 @@ require 'spec_helper' -describe Celluloid::IO::TCPSocket do +RSpec.describe Celluloid::IO::TCPSocket, library: :IO do let(:payload) { 'ohai' } let(:example_port) { assign_port } + let(:logger) { Specs::FakeLogger.current } context "inside Celluloid::IO" do @@ -22,10 +23,10 @@ it "returns the block evaluation" do server = ::TCPServer.new example_addr, example_port thread = Thread.new { server.accept } - + value = within_io_actor { Celluloid::IO::TCPSocket.open(example_addr, example_port) { true } } expect(value).to be_truthy - + server.close thread.terminate end @@ -102,6 +103,7 @@ end it "raises Errno::ECONNREFUSED when the connection is refused" do + allow(logger).to receive(:crash).with("Actor crashed!", Errno::ECONNREFUSED) expect { within_io_actor { ::TCPSocket.new(example_addr, example_port) } }.to raise_error(Errno::ECONNREFUSED) @@ -116,8 +118,9 @@ expect(Time.now - started_at).to be > 0.5 end end - + it "blocks until gets the next byte" do + allow(logger).to receive(:crash).with("Actor crashed!", Celluloid::TaskTimeout) with_connected_sockets(example_port) do |subject, peer| peer << 0x00 peer.flush @@ -135,6 +138,7 @@ context "readpartial" do it "raises EOFError when reading from a closed socket" do + allow(logger).to receive(:crash).with("Actor crashed!", EOFError) with_connected_sockets(example_port) do |subject, peer| peer.close expect { @@ -147,7 +151,8 @@ pending "not implemented" with_connected_sockets(example_port) do |subject, peer| - actor = ExampleActor.new + actor = with_wrapper_actor + allow(logger).to receive(:crash).with("Actor crashed!", IOError) begin read_future = actor.future.wrap do subject.readpartial(payload.size) @@ -164,7 +169,8 @@ it "raises IOError when partial reading from a socket the peer closed" do pending "async block running on receiver" with_connected_sockets(example_port) do |subject, peer| - actor = ExampleActor.new + actor = with_wrapper_actor + allow(logger).to receive(:crash).with("Actor crashed!", IOError) begin actor.async.wrap { sleep 0.01; peer.close } expect do diff --git a/spec/celluloid/io/udp_socket_spec.rb b/spec/celluloid/io/udp_socket_spec.rb index 7433fd2..adf5290 100644 --- a/spec/celluloid/io/udp_socket_spec.rb +++ b/spec/celluloid/io/udp_socket_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Celluloid::IO::UDPSocket do +RSpec.describe Celluloid::IO::UDPSocket, library: :IO do let(:payload) { 'ohai' } let(:example_port) { assign_port } subject do diff --git a/spec/celluloid/io/unix_server_spec.rb b/spec/celluloid/io/unix_server_spec.rb index 5b631cc..8bf6a64 100644 --- a/spec/celluloid/io/unix_server_spec.rb +++ b/spec/celluloid/io/unix_server_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Celluloid::IO::UNIXServer do +RSpec.describe Celluloid::IO::UNIXServer, library: :IO do let(:example_port) { assign_port } describe "#accept" do diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index dbae9cf..e0ad33f 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -describe Celluloid::IO::UNIXSocket do - +RSpec.describe Celluloid::IO::UNIXSocket, library: :IO do + if RUBY_PLATFORM == 'java' before(:each) do pending "jRuby support" @@ -11,6 +11,7 @@ let(:payload) { 'ohai' } let(:example_port) { assign_port } + let(:logger) { Specs::FakeLogger.current } context "inside Celluloid::IO" do it "connects to UNIX servers" do @@ -84,12 +85,14 @@ end it "raises Errno::ENOENT when the connection is refused" do + allow(logger).to receive(:crash).with("Actor crashed!", Errno::ENOENT) expect { within_io_actor { Celluloid::IO::UNIXSocket.open(example_unix_sock) } }.to raise_error(Errno::ENOENT) end it "raises EOFError when partial reading from a closed socket" do + allow(logger).to receive(:crash).with("Actor crashed!", EOFError) with_connected_unix_sockets do |subject, peer| peer.close expect { @@ -107,8 +110,9 @@ expect(Time.now - started_at).to be > 0.5 end end - + it "blocks until gets the next byte" do + allow(logger).to receive(:crash).with("Actor crashed!", Celluloid::TaskTimeout) with_connected_sockets(example_port) do |subject, peer| peer << 0x00 peer.flush diff --git a/spec/celluloid/io_spec.rb b/spec/celluloid/io_spec.rb index 47aa104..4134bee 100644 --- a/spec/celluloid/io_spec.rb +++ b/spec/celluloid/io_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Celluloid::IO do +RSpec.describe Celluloid::IO, library: :IO do context "copy_stream" do let(:host) { "127.0.0.1" } let(:port) { 23456 } @@ -18,4 +18,4 @@ expect(client.read(file.stat.size)).to eq my_own_bits end end -end \ No newline at end of file +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 01d9a33..b7028bd 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,124 +1,11 @@ -require 'celluloid/rspec' -require 'celluloid/io' - -Dir[ *Specs::INCLUDE_PATHS ].map { |f| require f } - -=begin -logfile = File.open(File.expand_path("../../log/test.log", __FILE__), 'a') -logfile.sync = true - -logger = Celluloid.logger = Logger.new(logfile) - -Celluloid.shutdown_timeout = 1 - -RSpec.configure do |config| - config.filter_run :focus => true - config.run_all_when_everything_filtered = true +require "rubygems" +require "bundler/setup" - config.around(:each) { |example| - Timeout.timeout(Specs::MAX_EXECUTION) { - example.run - } - } - - config.before do - Celluloid.logger = logger - Celluloid.shutdown - Celluloid.boot - FileUtils.rm("/tmp/cell_sock") if File.exist?("/tmp/cell_sock") - end -end -=end - -class ExampleActor - include Celluloid::IO - execute_block_on_receiver :wrap - - def wrap - yield - end +module Specs + ALLOW_SLOW_MAILBOXES = true # TODO: Remove hax. end -# Would use Addrinfo(addr,0) but the class is missing/unstable on RBX. -def assign_port - port = 12000 + Random.rand(1024) - attempts = 0 - begin - socket = ::TCPServer.new(example_addr, port) - rescue Errno::ECONNREFUSED, Errno::EADDRINUSE => ex - raise ex.class.new("Tried #{attempts} times to assign port.") unless attempts < Specs::MAX_ATTEMPTS - attempts += 1 - port += 1 - socket.close rescue nil - sleep 0.126 - retry - end - return port -ensure - socket.close rescue nil -end - -def example_addr; '127.0.0.1'; end -def example_unix_sock; '/tmp/cell_sock'; end - -def fixture_dir; Pathname.new File.expand_path("../fixtures", __FILE__); end - -def within_io_actor(&block) - actor = ExampleActor.new - actor.wrap(&block) -ensure - actor.terminate if actor.alive? -end - -def with_tcp_server(port) - server = Celluloid::IO::TCPServer.new(example_addr, port) - begin - yield server - ensure - server.close - end -end - -def with_unix_server - server = Celluloid::IO::UNIXServer.open(example_unix_sock) - begin - yield server - ensure - server.close - File.delete(example_unix_sock) - end -end - -def with_connected_sockets(port) - with_tcp_server(port) do |server| - client = Celluloid::IO::TCPSocket.new(example_addr, port) - peer = server.accept - - begin - yield peer, client - ensure - begin - client.close - peer.close - rescue - end - end - end -end - -def with_connected_unix_sockets - with_unix_server do |server| - client = Celluloid::IO::UNIXSocket.new(example_unix_sock) - peer = server.accept +require 'celluloid/rspec' +require 'celluloid/io' - begin - yield peer, client - ensure - begin - client.close - peer.close - rescue - end - end - end -end +Dir[ *Specs::INCLUDE_PATHS ].map { |f| require f } diff --git a/spec/support/examples/classes.rb b/spec/support/examples/classes.rb new file mode 100644 index 0000000..7005536 --- /dev/null +++ b/spec/support/examples/classes.rb @@ -0,0 +1,12 @@ +class WrapperActor + include Celluloid::IO + execute_block_on_receiver :wrap + + def wrap + yield + end +end + +def with_wrapper_actor + WrapperActor.new +end diff --git a/spec/support/examples/methods.rb b/spec/support/examples/methods.rb new file mode 100644 index 0000000..566c859 --- /dev/null +++ b/spec/support/examples/methods.rb @@ -0,0 +1,83 @@ +def fixture_dir; Pathname.new File.expand_path("../../../fixtures", __FILE__); end + +# Would use Addrinfo(addr,0) but the class is missing/unstable on RBX. +def assign_port + port = 12000 + Random.rand(1024) + attempts = 0 + begin + socket = ::TCPServer.new(example_addr, port) + rescue Errno::ECONNREFUSED, Errno::EADDRINUSE => ex + raise ex.class.new("Tried #{attempts} times to assign port.") unless attempts < Specs::MAX_ATTEMPTS + attempts += 1 + port += 1 + socket.close rescue nil + sleep 0.126 + retry + end + return port +ensure + socket.close rescue nil +end + +def example_addr; '127.0.0.1'; end +def example_unix_sock; '/tmp/cell_sock'; end + +def within_io_actor(&block) + actor = WrapperActor.new + actor.wrap(&block) +ensure + actor.terminate if actor.alive? rescue nil +end + +def with_tcp_server(port) + server = Celluloid::IO::TCPServer.new(example_addr, port) + begin + yield server + ensure + server.close + end +end + +def with_unix_server + server = Celluloid::IO::UNIXServer.open(example_unix_sock) + begin + yield server + ensure + server.close + File.delete(example_unix_sock) + end +end + +def with_connected_sockets(port) + with_tcp_server(port) do |server| + client = Celluloid::IO::TCPSocket.new(example_addr, port) + peer = server.accept + + begin + yield peer, client + ensure + begin + client.close + peer.close + rescue + end + end + end +end + +def with_connected_unix_sockets + with_unix_server do |server| + client = Celluloid::IO::UNIXSocket.new(example_unix_sock) + peer = server.accept + + begin + yield peer, client + ensure + begin + client.close + peer.close + rescue + end + end + end +end From 913fa88c7abd21cd7e96a28d2ea5a284a1728a72 Mon Sep 17 00:00:00 2001 From: //de Date: Sat, 26 Sep 2015 21:40:40 -0700 Subject: [PATCH 74/97] use CI config synced with Celluloid itself --- .travis.yml | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index e8ad3dd..e3dc5e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,34 +1,43 @@ script: rake ci language: ruby rvm: - - 2.2.0 - - 2.2.2 + - rbx-2 - jruby + - 2.2.2 + - 2.2.0 + - 2.1.4 + - 2.0.0 + - 1.9.3 - ruby-head - jruby-head - - rbx-2 - -# TODO: Put these back: -# * CELLULOID_TASK_CLASS=Fibered -# * CELLULOID_TASK_CLASS=Threaded -# For right now the imporant thing is to test BACKPORTED mode: matrix: fast_finish: true allow_failures: + - rvm: 1.9.3 - rvm: ruby-head - rvm: jruby-head - env: CELLULOID_BACKPORTED=true + - env: CELLULOID_BACKPORTED=false CELLULOID_LEAKTEST=1 + - env: CELLULOID_BACKPORTED=false CELLULOID_TASK_CLASS=Threaded + - env: CELLULOID_BACKPORTED=true CELLULOID_TASK_CLASS=Threaded env: + global: + - NUMBER_OF_PROCESSORS=4 CELLULOID_CONFIG_FILE=.env-ci matrix: - CELLULOID_BACKPORTED=true - CELLULOID_BACKPORTED=false - global: - - NUMBER_OF_PROCESSORS=2 CELLULOID_CONFIG_FILE=.env-ci + - CELLULOID_BACKPORTED=false CELLULOID_LEAKTEST=1 + - CELLULOID_BACKPORTED=false CELLULOID_TASK_CLASS=Threaded + - CELLULOID_BACKPORTED=true CELLULOID_TASK_CLASS=Threaded notifications: irc: "irc.freenode.org#celluloid" +before_install: + # Only use 1 job until Travis fixes the rbx --jobs issue. + - if [ "$TRAVIS_RUBY_VERSION" == "rbx-2" ] ; then export BUNDLE_JOBS=1 ; else export BUNDLE_JOBS=4; fi + sudo: false install: bundle install --without=development From 9a6f64246454c17f90d647e82b95bdec4acf12a2 Mon Sep 17 00:00:00 2001 From: //de Date: Mon, 28 Sep 2015 10:41:22 -0700 Subject: [PATCH 75/97] update culture gems, set new version, update changelog --- CHANGES.md | 12 +++++++++++- culture | 2 +- lib/celluloid/io/version.rb | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 912c82f..817cc6d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,15 @@ -HEAD +0.17.2 (2015-09-28) ----- +* Revamped test suite, using shared RSpec configuration layer provided by Celluloid itself. +* Updated gem dependencies provided by Celluloid::Sync... extraneous gems removed, or marked as development dependencies. + +0.17.1 (2015-08-24) +----- +* Minor bug fixes. Synchronize gem dependencies. + +0.17.0 (2015-08-07) +----- +* Compatibility with Celluloid 0.17.0+ * Adjust class name for Celluloid::Mailbox::Evented, per 0.17.0 of Celluloid. 0.16.2 (2015-01-30) diff --git a/culture b/culture index c0ae083..da888c9 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit c0ae083774874f3975cd442eb57627979d0b95fd +Subproject commit da888c98093565f78bfaedcfb7bd1269f23358f7 diff --git a/lib/celluloid/io/version.rb b/lib/celluloid/io/version.rb index 46be987..5f524c4 100644 --- a/lib/celluloid/io/version.rb +++ b/lib/celluloid/io/version.rb @@ -1,5 +1,5 @@ module Celluloid module IO - VERSION = "0.17.1" + VERSION = "0.17.2" end end From 676e750cdde40f3fafe2fdd90f50ca7023e6163e Mon Sep 17 00:00:00 2001 From: //de Date: Mon, 28 Sep 2015 10:54:14 -0700 Subject: [PATCH 76/97] resync culture one last time --- culture | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/culture b/culture index da888c9..29baead 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit da888c98093565f78bfaedcfb7bd1269f23358f7 +Subproject commit 29baead42e0ce86b09ed94fe9bcb23160749565d From 4a4d2b97a7d28a0e1b9d67cf98550fde3e0f609a Mon Sep 17 00:00:00 2001 From: //de Date: Mon, 28 Sep 2015 11:13:49 -0700 Subject: [PATCH 77/97] rubocop pass for celluloid/culture#33 --- .rubocop.yml | 2 ++ Gemfile | 1 - Guardfile | 4 +-- Rakefile | 6 ++-- celluloid-io.gemspec | 10 +++--- culture | 2 +- examples/echo_client.rb | 7 ++-- examples/echo_server.rb | 4 +-- examples/echo_unix_client.rb | 5 ++- examples/echo_unix_server.rb | 5 ++- lib/celluloid/io.rb | 30 ++++++++-------- lib/celluloid/io/dns_resolver.rb | 18 +++++----- lib/celluloid/io/reactor.rb | 12 +++---- lib/celluloid/io/ssl_server.rb | 3 +- lib/celluloid/io/ssl_socket.rb | 32 +++++++++-------- lib/celluloid/io/tcp_socket.rb | 20 +++++------ lib/celluloid/io/unix_socket.rb | 10 +++--- spec/celluloid/io/actor_spec.rb | 2 +- spec/celluloid/io/dns_resolver_spec.rb | 14 ++++---- spec/celluloid/io/mailbox_spec.rb | 2 +- spec/celluloid/io/reactor_spec.rb | 2 +- spec/celluloid/io/ssl_server_spec.rb | 4 +-- spec/celluloid/io/ssl_socket_spec.rb | 50 +++++++++++++------------- spec/celluloid/io/tcp_server_spec.rb | 4 +-- spec/celluloid/io/tcp_socket_spec.rb | 29 ++++++++------- spec/celluloid/io/udp_socket_spec.rb | 4 +-- spec/celluloid/io/unix_server_spec.rb | 16 ++++----- spec/celluloid/io/unix_socket_spec.rb | 31 ++++++++-------- spec/celluloid/io_spec.rb | 6 ++-- spec/spec_helper.rb | 6 ++-- spec/support/examples/methods.rb | 15 +++++--- 31 files changed, 179 insertions(+), 177 deletions(-) create mode 100644 .rubocop.yml diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..39e653a --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,2 @@ +inherit_from: + - culture/rubocop/rubocop.yml \ No newline at end of file diff --git a/Gemfile b/Gemfile index 58da518..c16a128 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,3 @@ require File.expand_path("../culture/sync", __FILE__) Celluloid::Sync::Gemfile[self] - diff --git a/Guardfile b/Guardfile index 1745569..f8dd8d8 100644 --- a/Guardfile +++ b/Guardfile @@ -1,5 +1,5 @@ -guard 'rspec', :cli => '--format documentation' do +guard "rspec", cli: "--format documentation" do watch(%r{^spec/.+_spec\.rb$}) watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } - watch('spec/spec_helper.rb') { "spec/" } + watch("spec/spec_helper.rb") { "spec/" } end diff --git a/Rakefile b/Rakefile index f43f2b6..ad04838 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,6 @@ #!/usr/bin/env rake -require 'bundler/gem_tasks' +require "bundler/gem_tasks" Dir["tasks/**/*.task"].each { |task| load task } -task :default => :spec -task :ci => %w(spec benchmark) +task default: :spec +task ci: %w(spec benchmark) diff --git a/celluloid-io.gemspec b/celluloid-io.gemspec index e5a231c..48112f0 100644 --- a/celluloid-io.gemspec +++ b/celluloid-io.gemspec @@ -4,21 +4,21 @@ require File.expand_path("../culture/sync", __FILE__) Gem::Specification.new do |gem| gem.name = "celluloid-io" gem.version = Celluloid::IO::VERSION - gem.license = 'MIT' + gem.license = "MIT" gem.authors = ["Tony Arcieri", "Donovan Keme"] gem.email = ["tony.arcieri@gmail.com", "code@extremist.digital"] gem.description = "Evented IO for Celluloid actors" gem.summary = "Celluloid::IO allows you to monitor multiple IO objects within a Celluloid actor" gem.homepage = "http://github.com/celluloid/celluloid-io" - gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } gem.files = `git ls-files`.split("\n") gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") gem.require_paths = ["lib"] Celluloid::Sync::Gemspec[gem] - - gem.add_dependency 'nio4r', '>= 1.1' - gem.add_development_dependency 'rb-fsevent', '~> 0.9.1' if RUBY_PLATFORM =~ /darwin/ + gem.add_dependency "nio4r", ">= 1.1" + + gem.add_development_dependency "rb-fsevent", "~> 0.9.1" if RUBY_PLATFORM =~ /darwin/ end diff --git a/culture b/culture index 29baead..d76f772 160000 --- a/culture +++ b/culture @@ -1 +1 @@ -Subproject commit 29baead42e0ce86b09ed94fe9bcb23160749565d +Subproject commit d76f772a2d669be2028d8be1c8baa95f7d3174a0 diff --git a/examples/echo_client.rb b/examples/echo_client.rb index 70bd600..9950ba5 100644 --- a/examples/echo_client.rb +++ b/examples/echo_client.rb @@ -1,8 +1,8 @@ #!/usr/bin/env ruby -require 'rubygems' -require 'bundler/setup' -require 'celluloid/io' +require "rubygems" +require "bundler/setup" +require "celluloid/io" class EchoClient include Celluloid::IO @@ -18,7 +18,6 @@ def echo(s) @socket.write(s) @socket.readpartial(4096) end - end client = EchoClient.new("127.0.0.1", 1234) diff --git a/examples/echo_server.rb b/examples/echo_server.rb index e40d053..38a5178 100755 --- a/examples/echo_server.rb +++ b/examples/echo_server.rb @@ -2,8 +2,8 @@ # # Run this as: bundle exec examples/echo_server.rb -require 'bundler/setup' -require 'celluloid/io' +require "bundler/setup" +require "celluloid/io" class EchoServer include Celluloid::IO diff --git a/examples/echo_unix_client.rb b/examples/echo_unix_client.rb index 803d675..27eafe6 100644 --- a/examples/echo_unix_client.rb +++ b/examples/echo_unix_client.rb @@ -1,5 +1,5 @@ -require 'bundler/setup' -require 'celluloid/io' +require "bundler/setup" +require "celluloid/io" class EchoUNIXClient include Celluloid::IO @@ -22,7 +22,6 @@ def echo(msg) def finalize @socket.close if @socket end - end c = EchoUNIXClient.new("/tmp/sock_test") diff --git a/examples/echo_unix_server.rb b/examples/echo_unix_server.rb index 1c7b028..4d5625a 100644 --- a/examples/echo_unix_server.rb +++ b/examples/echo_unix_server.rb @@ -1,5 +1,5 @@ -require 'bundler/setup' -require 'celluloid/io' +require "bundler/setup" +require "celluloid/io" class EchoUNIXServer include Celluloid::IO @@ -38,7 +38,6 @@ def finalize File.delete(@socket_path) end end - end supervisor = EchoUNIXServer.supervise("/tmp/sock_test") diff --git a/lib/celluloid/io.rb b/lib/celluloid/io.rb index 2b2a910..ddb9960 100644 --- a/lib/celluloid/io.rb +++ b/lib/celluloid/io.rb @@ -1,19 +1,19 @@ -require 'celluloid/io/version' +require "celluloid/io/version" -require 'celluloid' -require 'celluloid/io/dns_resolver' -require 'celluloid/io/mailbox' -require 'celluloid/io/reactor' -require 'celluloid/io/stream' +require "celluloid" +require "celluloid/io/dns_resolver" +require "celluloid/io/mailbox" +require "celluloid/io/reactor" +require "celluloid/io/stream" -require 'celluloid/io/tcp_server' -require 'celluloid/io/tcp_socket' -require 'celluloid/io/udp_socket' -require 'celluloid/io/unix_server' -require 'celluloid/io/unix_socket' +require "celluloid/io/tcp_server" +require "celluloid/io/tcp_socket" +require "celluloid/io/udp_socket" +require "celluloid/io/unix_server" +require "celluloid/io/unix_socket" -require 'celluloid/io/ssl_server' -require 'celluloid/io/ssl_socket' +require "celluloid/io/ssl_server" +require "celluloid/io/ssl_socket" module Celluloid # Actors with evented IO support @@ -30,13 +30,13 @@ def self.evented? actor = Thread.current[:celluloid_actor] actor && actor.mailbox.is_a?(Celluloid::IO::Mailbox) end - + def self.try_convert(src) ::IO.try_convert(src) end def self.copy_stream(src, dst, copy_length = nil, src_offset = nil) - raise NotImplementedError, "length/offset not supported" if copy_length || src_offset + fail NotImplementedError, "length/offset not supported" if copy_length || src_offset src, dst = try_convert(src), try_convert(dst) diff --git a/lib/celluloid/io/dns_resolver.rb b/lib/celluloid/io/dns_resolver.rb index 8bebec5..a1615de 100644 --- a/lib/celluloid/io/dns_resolver.rb +++ b/lib/celluloid/io/dns_resolver.rb @@ -1,5 +1,5 @@ -require 'ipaddr' -require 'resolv' +require "ipaddr" +require "resolv" module Celluloid module IO @@ -35,7 +35,7 @@ def initialize def resolve(hostname) if host = resolve_hostname(hostname) unless ip_address = resolve_host(host) - raise Resolv::ResolvError, "invalid entry in hosts file: #{host}" + fail Resolv::ResolvError, "invalid entry in hosts file: #{host}" end return ip_address end @@ -81,17 +81,17 @@ def resolve_host(host) end def resolve_ip(klass, host) - begin - klass.create(host) - rescue ArgumentError - end + + klass.create(host) + rescue ArgumentError + end private def get_address(host) - Resolv::Hosts.new(host).get_address. - rescue + Resolv::Hosts.new(host).get_address + .rescue end end end diff --git a/lib/celluloid/io/reactor.rb b/lib/celluloid/io/reactor.rb index 22da5e8..9be8ebc 100644 --- a/lib/celluloid/io/reactor.rb +++ b/lib/celluloid/io/reactor.rb @@ -1,4 +1,4 @@ -require 'nio' +require "nio" module Celluloid module IO @@ -29,24 +29,24 @@ def wait_writable(io) # Wait for the given IO operation to complete def wait(io, set) # zomg ugly type conversion :( - unless io.is_a?(::IO) or io.is_a?(OpenSSL::SSL::SSLSocket) + unless io.is_a?(::IO) || io.is_a?(OpenSSL::SSL::SSLSocket) if io.respond_to? :to_io io = io.to_io elsif ::IO.respond_to? :try_convert io = ::IO.try_convert(io) end - raise TypeError, "can't convert #{io.class} into IO" unless io.is_a?(::IO) + fail TypeError, "can't convert #{io.class} into IO" unless io.is_a?(::IO) end monitor = @selector.register(io, set) monitor.value = Task.current - + begin Task.suspend :iowait ensure - # In all cases we want to ensure that the monitor is closed once we - # have woken up. However, in some cases, the monitor is already + # In all cases we want to ensure that the monitor is closed once we + # have woken up. However, in some cases, the monitor is already # invalid, e.g. in the case that we are terminating. We catch this # case explicitly. monitor.close diff --git a/lib/celluloid/io/ssl_server.rb b/lib/celluloid/io/ssl_server.rb index 9d98b90..5d313d0 100644 --- a/lib/celluloid/io/ssl_server.rb +++ b/lib/celluloid/io/ssl_server.rb @@ -1,4 +1,4 @@ -require 'socket' +require "socket" module Celluloid module IO @@ -33,4 +33,3 @@ def accept end end end - diff --git a/lib/celluloid/io/ssl_socket.rb b/lib/celluloid/io/ssl_socket.rb index 8a8bdb9..686da0a 100644 --- a/lib/celluloid/io/ssl_socket.rb +++ b/lib/celluloid/io/ssl_socket.rb @@ -1,4 +1,4 @@ -require 'openssl' +require "openssl" module Celluloid module IO @@ -7,19 +7,19 @@ class SSLSocket < Stream extend Forwardable def_delegators :@socket, - :read_nonblock, - :write_nonblock, - :close, - :closed?, - :cert, - :cipher, - :client_ca, - :peeraddr, - :peer_cert, - :peer_cert_chain, - :post_connection_check, - :verify_result, - :sync_close= + :read_nonblock, + :write_nonblock, + :close, + :closed?, + :cert, + :cipher, + :client_ca, + :peeraddr, + :peer_cert, + :peer_cert_chain, + :post_connection_check, + :verify_result, + :sync_close= def initialize(io, ctx = OpenSSL::SSL::SSLContext.new) super() @@ -47,7 +47,9 @@ def accept retry end - def to_io; @socket; end + def to_io + @socket + end end end end diff --git a/lib/celluloid/io/tcp_socket.rb b/lib/celluloid/io/tcp_socket.rb index 1cf98d5..273a168 100644 --- a/lib/celluloid/io/tcp_socket.rb +++ b/lib/celluloid/io/tcp_socket.rb @@ -1,5 +1,5 @@ -require 'socket' -require 'resolv' +require "socket" +require "resolv" module Celluloid module IO @@ -12,7 +12,7 @@ class TCPSocket < Stream # Open a TCP socket, yielding it to the given block and closing it # automatically when done (if a block is given) - def self.open(*args, &block) + def self.open(*args, &_block) sock = new(*args) return sock unless block_given? @@ -41,7 +41,7 @@ def initialize(remote_host, remote_port = nil, local_host = nil, local_port = ni @socket = remote_host return elsif remote_port.nil? - raise ArgumentError, "wrong number of arguments (1 for 2)" + fail ArgumentError, "wrong number of arguments (1 for 2)" end # Is it an IPv4 address? @@ -61,7 +61,7 @@ def initialize(remote_host, remote_port = nil, local_host = nil, local_port = ni # Guess it's not an IP address, so let's try DNS unless @addr addrs = Array(DNSResolver.new.resolve(remote_host)) - raise Resolv::ResolvError, "DNS result has no information for #{remote_host}" if addrs.empty? + fail Resolv::ResolvError, "DNS result has no information for #{remote_host}" if addrs.empty? # Pseudorandom round-robin DNS support :/ @addr = addrs[rand(addrs.size)] @@ -72,7 +72,7 @@ def initialize(remote_host, remote_port = nil, local_host = nil, local_port = ni family = Socket::AF_INET when Resolv::IPv6 family = Socket::AF_INET6 - else raise ArgumentError, "unsupported address class: #{@addr.class}" + else fail ArgumentError, "unsupported address class: #{@addr.class}" end @socket = Socket.new(family, Socket::SOCK_STREAM, 0) @@ -88,7 +88,7 @@ def initialize(remote_host, remote_port = nil, local_host = nil, local_port = ni # HAX: for some reason we need to finish_connect ourselves on JRuby # This logic is unnecessary but JRuby still throws Errno::EINPROGRESS # if we retry the non-blocking connect instead of just finishing it - retry unless RUBY_PLATFORM == 'java' && @socket.to_channel.finish_connect + retry unless RUBY_PLATFORM == "java" && @socket.to_channel.finish_connect rescue Errno::EISCONN # We're now connected! Yay exceptions for flow control # NOTE: This is the approach the Ruby stdlib docs suggest ;_; @@ -101,14 +101,14 @@ def to_io # Receives a message def recv(maxlen, flags = nil) - raise NotImplementedError, "flags not supported" if flags && !flags.zero? + fail NotImplementedError, "flags not supported" if flags && !flags.zero? readpartial(maxlen) end # Send a message def send(msg, flags, dest_sockaddr = nil) - raise NotImplementedError, "dest_sockaddr not supported" if dest_sockaddr - raise NotImplementedError, "flags not supported" unless flags.zero? + fail NotImplementedError, "dest_sockaddr not supported" if dest_sockaddr + fail NotImplementedError, "flags not supported" unless flags.zero? write(msg) end end diff --git a/lib/celluloid/io/unix_socket.rb b/lib/celluloid/io/unix_socket.rb index e5d4d50..262f946 100644 --- a/lib/celluloid/io/unix_socket.rb +++ b/lib/celluloid/io/unix_socket.rb @@ -1,4 +1,4 @@ -require 'socket' +require "socket" module Celluloid module IO @@ -10,7 +10,7 @@ class UNIXSocket < Stream # Open a UNIX connection. def self.open(socket_path, &block) - self.new(socket_path, &block) + new(socket_path, &block) end # Convert a Ruby UNIXSocket into a Celluloid::IO::UNIXSocket @@ -31,9 +31,9 @@ def initialize(socket_path, &block) # FIXME: not doing non-blocking connect @socket = if block - ::UNIXSocket.open(socket_path, &block) - else - ::UNIXSocket.new(socket_path) + ::UNIXSocket.open(socket_path, &block) + else + ::UNIXSocket.new(socket_path) end end diff --git a/spec/celluloid/io/actor_spec.rb b/spec/celluloid/io/actor_spec.rb index 7798b9d..e01fc7d 100644 --- a/spec/celluloid/io/actor_spec.rb +++ b/spec/celluloid/io/actor_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO, library: :IO do it_behaves_like "a Celluloid Actor", Celluloid::IO diff --git a/spec/celluloid/io/dns_resolver_spec.rb b/spec/celluloid/io/dns_resolver_spec.rb index 8360f43..81c13b6 100644 --- a/spec/celluloid/io/dns_resolver_spec.rb +++ b/spec/celluloid/io/dns_resolver_spec.rb @@ -1,18 +1,18 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO::DNSResolver, library: :IO do context '#resolve' do - it 'resolves hostnames statically from hosts file without nameservers' do + it "resolves hostnames statically from hosts file without nameservers" do # /etc/resolv.conf doesn't exist on Mac OSX when no networking is # disabled, thus .nameservers would return nil expect(Celluloid::IO::DNSResolver).to receive(:nameservers).at_most(:once) { nil } resolver = Celluloid::IO::DNSResolver.new - expect(resolver.resolve('localhost')).to eq Resolv::IPv4.create("127.0.0.1") + expect(resolver.resolve("localhost")).to eq Resolv::IPv4.create("127.0.0.1") end - it 'resolves hostnames' do + it "resolves hostnames" do resolver = Celluloid::IO::DNSResolver.new - expect(resolver.resolve('localhost')).to eq Resolv::IPv4.create("127.0.0.1") + expect(resolver.resolve("localhost")).to eq Resolv::IPv4.create("127.0.0.1") end it "resolves domain names" do @@ -26,7 +26,7 @@ resolver = Celluloid::IO::DNSResolver.new results = resolver.resolve("www.google.com") if results.is_a?(Array) - results.all? {|i| expect(i).to be_an_instance_of(Resolv::IPv4) } + results.all? { |i| expect(i).to be_an_instance_of(Resolv::IPv4) } else expect(results).to be_an_instance_of(Resolv::IPv4) end @@ -34,7 +34,7 @@ # single entry. results = resolver.resolve("www.yahoo.com") if results.is_a?(Array) - results.all? {|i| expect(i).to be_an_instance_of(Resolv::IPv4) } + results.all? { |i| expect(i).to be_an_instance_of(Resolv::IPv4) } else expect(results).to be_an_instance_of(Resolv::IPv4) end diff --git a/spec/celluloid/io/mailbox_spec.rb b/spec/celluloid/io/mailbox_spec.rb index db2abef..b535999 100644 --- a/spec/celluloid/io/mailbox_spec.rb +++ b/spec/celluloid/io/mailbox_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO::Mailbox, library: :IO do it_behaves_like "a Celluloid Mailbox" diff --git a/spec/celluloid/io/reactor_spec.rb b/spec/celluloid/io/reactor_spec.rb index 62fc4eb..fcbf386 100644 --- a/spec/celluloid/io/reactor_spec.rb +++ b/spec/celluloid/io/reactor_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO::Reactor, library: :IO do let(:payload) { "balls" } diff --git a/spec/celluloid/io/ssl_server_spec.rb b/spec/celluloid/io/ssl_server_spec.rb index 18e97b6..f18b1fa 100644 --- a/spec/celluloid/io/ssl_server_spec.rb +++ b/spec/celluloid/io/ssl_server_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO::SSLServer, library: :IO do let(:client_cert) { OpenSSL::X509::Certificate.new fixture_dir.join("client.crt").read } @@ -21,7 +21,7 @@ end describe "#accept" do - let(:payload) { 'ohai' } + let(:payload) { "ohai" } context "inside Celluloid::IO" do it "should be evented" do diff --git a/spec/celluloid/io/ssl_socket_spec.rb b/spec/celluloid/io/ssl_socket_spec.rb index fc87fe7..327b773 100644 --- a/spec/celluloid/io/ssl_socket_spec.rb +++ b/spec/celluloid/io/ssl_socket_spec.rb @@ -1,9 +1,9 @@ -require 'spec_helper' -require 'openssl' +require "spec_helper" +require "openssl" RSpec.describe Celluloid::IO::SSLSocket, library: :IO do - let(:request) { 'ping' } - let(:response) { 'pong' } + let(:request) { "ping" } + let(:response) { "pong" } let(:example_port) { assign_port } let(:client_cert) { OpenSSL::X509::Certificate.new fixture_dir.join("client.crt").read } @@ -15,28 +15,28 @@ end end - after(:each) { + after(:each) do client.close rescue nil server.close rescue nil - } + end let(:client) do attempts = 0 socket = begin - Timeout.timeout(Specs::MAX_EXECUTION) { - begin - TCPSocket.new example_addr, example_port - rescue Errno::ECONNREFUSED - raise if attempts >= Specs::MAX_ATTEMPTS - attempts += 1 - # HAX: sometimes this fails to connect? o_O - # ... This can often fail 20 times in a row ... so yeah - # This is quite likely due to the Thread.pass style spinlocks for startup - # Seems gimpy, but sleep and retry - sleep 0.0126 - retry + Timeout.timeout(Specs::MAX_EXECUTION) do + begin + TCPSocket.new example_addr, example_port + rescue Errno::ECONNREFUSED + raise if attempts >= Specs::MAX_ATTEMPTS + attempts += 1 + # HAX: sometimes this fails to connect? o_O + # ... This can often fail 20 times in a row ... so yeah + # This is quite likely due to the Thread.pass style spinlocks for startup + # Seems gimpy, but sleep and retry + sleep 0.0126 + retry + end end - } rescue => ex attempted = "Tried #{attempts} times to instantiate socket." raise ex.class.new(attempted) @@ -77,7 +77,7 @@ context "duck typing ::SSLSocket" do it "responds to #peeraddr" do with_ssl_sockets do |ssl_client, ssl_peer| - expect{ ssl_client.peeraddr }.to_not raise_error + expect { ssl_client.peeraddr }.to_not raise_error end end end @@ -96,7 +96,7 @@ end it "starts SSL on a connected TCP socket" do - if RUBY_PLATFORM == 'java' + if RUBY_PLATFORM == "java" pending "JRuby support" fail "Bypassing potential deadlock." end @@ -136,7 +136,7 @@ end it "starts SSL on a connected TCP socket" do - if RUBY_PLATFORM == 'java' + if RUBY_PLATFORM == "java" pending "JRuby support" fail "Bypassing potential deadlock." end @@ -164,7 +164,7 @@ it "knows its cert" do # FIXME: seems bad? o_O - pending "wtf is wrong with this on JRuby" if RUBY_PLATFORM == 'java' + pending "wtf is wrong with this on JRuby" if RUBY_PLATFORM == "java" with_ssl_sockets do |ssl_client| expect(ssl_client.cert.to_der).to eq(client_cert.to_der) end @@ -192,7 +192,7 @@ it "knows its client_ca" do # jruby-openssl does not implement this method - pending "jruby-openssl support" if RUBY_PLATFORM == 'java' + pending "jruby-openssl support" if RUBY_PLATFORM == "java" with_ssl_sockets do |ssl_client| expect(ssl_client.client_ca).to eq(ssl_client.to_io.client_ca) @@ -201,7 +201,7 @@ it "verifies peer certificates" do # FIXME: JRuby seems to be giving the wrong result here o_O - pending "jruby-openssl support" if RUBY_PLATFORM == 'java' + pending "jruby-openssl support" if RUBY_PLATFORM == "java" with_ssl_sockets do |ssl_client, ssl_peer| expect(ssl_client.verify_result).to eq(OpenSSL::X509::V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index 452e605..1987f73 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -1,8 +1,8 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO::TCPServer, library: :IO do context "#accept" do - let(:payload) { 'ohai' } + let(:payload) { "ohai" } let(:example_port) { assign_port } it "can be initialized without a host" do diff --git a/spec/celluloid/io/tcp_socket_spec.rb b/spec/celluloid/io/tcp_socket_spec.rb index 9500012..ee87912 100644 --- a/spec/celluloid/io/tcp_socket_spec.rb +++ b/spec/celluloid/io/tcp_socket_spec.rb @@ -1,12 +1,11 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO::TCPSocket, library: :IO do - let(:payload) { 'ohai' } + let(:payload) { "ohai" } let(:example_port) { assign_port } let(:logger) { Specs::FakeLogger.current } context "inside Celluloid::IO" do - describe ".open" do it "returns the open socket" do server = ::TCPServer.new example_addr, example_port @@ -104,16 +103,16 @@ it "raises Errno::ECONNREFUSED when the connection is refused" do allow(logger).to receive(:crash).with("Actor crashed!", Errno::ECONNREFUSED) - expect { + expect do within_io_actor { ::TCPSocket.new(example_addr, example_port) } - }.to raise_error(Errno::ECONNREFUSED) + end.to raise_error(Errno::ECONNREFUSED) end - context 'eof?' do + context "eof?" do it "blocks actor then returns by close" do with_connected_sockets(example_port) do |subject, peer| started_at = Time.now - Thread.new{ sleep 0.5; peer.close; } + Thread.new { sleep 0.5; peer.close; } within_io_actor { subject.eof? } expect(Time.now - started_at).to be > 0.5 end @@ -124,14 +123,14 @@ with_connected_sockets(example_port) do |subject, peer| peer << 0x00 peer.flush - expect { - within_io_actor { + expect do + within_io_actor do subject.read(1) - Celluloid.timeout(0.5) { + Celluloid.timeout(0.5) do expect(subject.eof?).to be_falsey - } - } - }.to raise_error(Celluloid::TaskTimeout) + end + end + end.to raise_error(Celluloid::TaskTimeout) end end end @@ -141,9 +140,9 @@ allow(logger).to receive(:crash).with("Actor crashed!", EOFError) with_connected_sockets(example_port) do |subject, peer| peer.close - expect { + expect do within_io_actor { subject.readpartial(payload.size) } - }.to raise_error(EOFError) + end.to raise_error(EOFError) end end diff --git a/spec/celluloid/io/udp_socket_spec.rb b/spec/celluloid/io/udp_socket_spec.rb index adf5290..bdb3fa4 100644 --- a/spec/celluloid/io/udp_socket_spec.rb +++ b/spec/celluloid/io/udp_socket_spec.rb @@ -1,7 +1,7 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO::UDPSocket, library: :IO do - let(:payload) { 'ohai' } + let(:payload) { "ohai" } let(:example_port) { assign_port } subject do Celluloid::IO::UDPSocket.new.tap do |sock| diff --git a/spec/celluloid/io/unix_server_spec.rb b/spec/celluloid/io/unix_server_spec.rb index 8bf6a64..ff2ae93 100644 --- a/spec/celluloid/io/unix_server_spec.rb +++ b/spec/celluloid/io/unix_server_spec.rb @@ -1,11 +1,10 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO::UNIXServer, library: :IO do let(:example_port) { assign_port } describe "#accept" do - - let(:payload) { 'ohai' } + let(:payload) { "ohai" } context "inside Celluloid::IO" do it "should be evented" do @@ -15,7 +14,7 @@ end it "accepts a connection and returns a Celluloid::IO::UNIXSocket" do - pending if RUBY_PLATFORM == 'java' + pending if RUBY_PLATFORM == "java" with_unix_server do |subject| thread = Thread.new { UNIXSocket.new(example_unix_sock) } peer = within_io_actor { subject.accept } @@ -30,9 +29,9 @@ it "raises if server already up" do with_unix_server do |subject| within_io_actor do - expect { + expect do Celluloid::IO::UNIXServer.open(example_unix_sock) - }.to raise_error(Errno::EADDRINUSE) + end.to raise_error(Errno::EADDRINUSE) end end end @@ -58,12 +57,11 @@ it "raises if server already up" do with_unix_server do |subject| - expect { + expect do Celluloid::IO::UNIXServer.open(example_unix_sock) - }.to raise_error(Errno::EADDRINUSE) + end.to raise_error(Errno::EADDRINUSE) end end - end end end diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index e0ad33f..038be15 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -1,15 +1,14 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO::UNIXSocket, library: :IO do - - if RUBY_PLATFORM == 'java' + if RUBY_PLATFORM == "java" before(:each) do pending "jRuby support" fail "Avoid potential deadlock under jRuby" end end - let(:payload) { 'ohai' } + let(:payload) { "ohai" } let(:example_port) { assign_port } let(:logger) { Specs::FakeLogger.current } @@ -86,26 +85,26 @@ it "raises Errno::ENOENT when the connection is refused" do allow(logger).to receive(:crash).with("Actor crashed!", Errno::ENOENT) - expect { + expect do within_io_actor { Celluloid::IO::UNIXSocket.open(example_unix_sock) } - }.to raise_error(Errno::ENOENT) + end.to raise_error(Errno::ENOENT) end it "raises EOFError when partial reading from a closed socket" do allow(logger).to receive(:crash).with("Actor crashed!", EOFError) with_connected_unix_sockets do |subject, peer| peer.close - expect { + expect do within_io_actor { subject.readpartial(payload.size) } - }.to raise_error(EOFError) + end.to raise_error(EOFError) end end - context 'eof?' do + context "eof?" do it "blocks actor then returns by close" do with_connected_sockets(example_port) do |subject, peer| started_at = Time.now - Thread.new{ sleep 0.5; peer.close; } + Thread.new { sleep 0.5; peer.close; } within_io_actor { subject.eof? } expect(Time.now - started_at).to be > 0.5 end @@ -116,14 +115,14 @@ with_connected_sockets(example_port) do |subject, peer| peer << 0x00 peer.flush - expect { - within_io_actor { + expect do + within_io_actor do subject.read(1) - Celluloid.timeout(0.5) { + Celluloid.timeout(0.5) do expect(subject.eof?).to be_falsey - } - } - }.to raise_error(Celluloid::TaskTimeout) + end + end + end.to raise_error(Celluloid::TaskTimeout) end end end diff --git a/spec/celluloid/io_spec.rb b/spec/celluloid/io_spec.rb index 4134bee..323f59a 100644 --- a/spec/celluloid/io_spec.rb +++ b/spec/celluloid/io_spec.rb @@ -1,9 +1,9 @@ -require 'spec_helper' +require "spec_helper" RSpec.describe Celluloid::IO, library: :IO do context "copy_stream" do let(:host) { "127.0.0.1" } - let(:port) { 23456 } + let(:port) { 23_456 } it "copies streams from Celluloid::IO sockets" do server = described_class::TCPServer.new(host, port) @@ -12,7 +12,7 @@ expect(peer).to be_a described_class::TCPSocket my_own_bits = File.read(__FILE__) - file = File.open(__FILE__, 'r') + file = File.open(__FILE__, "r") described_class.copy_stream(file, peer) expect(client.read(file.stat.size)).to eq my_own_bits diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b7028bd..a42a769 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,7 +5,7 @@ module Specs ALLOW_SLOW_MAILBOXES = true # TODO: Remove hax. end -require 'celluloid/rspec' -require 'celluloid/io' +require "celluloid/rspec" +require "celluloid/io" -Dir[ *Specs::INCLUDE_PATHS ].map { |f| require f } +Dir[*Specs::INCLUDE_PATHS].map { |f| require f } diff --git a/spec/support/examples/methods.rb b/spec/support/examples/methods.rb index 566c859..2a65916 100644 --- a/spec/support/examples/methods.rb +++ b/spec/support/examples/methods.rb @@ -1,8 +1,10 @@ -def fixture_dir; Pathname.new File.expand_path("../../../fixtures", __FILE__); end +def fixture_dir + Pathname.new File.expand_path("../../../fixtures", __FILE__) +end # Would use Addrinfo(addr,0) but the class is missing/unstable on RBX. def assign_port - port = 12000 + Random.rand(1024) + port = 12_000 + Random.rand(1024) attempts = 0 begin socket = ::TCPServer.new(example_addr, port) @@ -19,8 +21,13 @@ def assign_port socket.close rescue nil end -def example_addr; '127.0.0.1'; end -def example_unix_sock; '/tmp/cell_sock'; end +def example_addr + "127.0.0.1" +end + +def example_unix_sock + "/tmp/cell_sock" +end def within_io_actor(&block) actor = WrapperActor.new From 85cee9da22ef5e94ba0abfd46454a2d56572aff4 Mon Sep 17 00:00:00 2001 From: //de Date: Wed, 30 Sep 2015 12:22:30 -0700 Subject: [PATCH 78/97] fix getaddress call for Resolv::Hosts --- lib/celluloid/io/dns_resolver.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/celluloid/io/dns_resolver.rb b/lib/celluloid/io/dns_resolver.rb index a1615de..7def5b5 100644 --- a/lib/celluloid/io/dns_resolver.rb +++ b/lib/celluloid/io/dns_resolver.rb @@ -61,7 +61,8 @@ def resolve_hostname(hostname) # Resolv::Hosts#getaddresses pushes onto a stack # so since we want the first occurance, simply # pop off the stack. - resolv.getaddresses(hostname).pop rescue nil + resolv.getaddresses(hostname).pop + rescue end def resolv @@ -81,17 +82,15 @@ def resolve_host(host) end def resolve_ip(klass, host) - klass.create(host) rescue ArgumentError - end private def get_address(host) - Resolv::Hosts.new(host).get_address - .rescue + Resolv::Hosts.new(host).getaddress + rescue end end end From f28c5ebe935970f4141ca16632e7502ee5cdabc3 Mon Sep 17 00:00:00 2001 From: //de Date: Wed, 30 Sep 2015 12:37:38 -0700 Subject: [PATCH 79/97] update release date, remove leak test from CI --- .travis.yml | 2 -- CHANGES.md | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index e3dc5e7..5a569b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,6 @@ matrix: - rvm: ruby-head - rvm: jruby-head - env: CELLULOID_BACKPORTED=true - - env: CELLULOID_BACKPORTED=false CELLULOID_LEAKTEST=1 - env: CELLULOID_BACKPORTED=false CELLULOID_TASK_CLASS=Threaded - env: CELLULOID_BACKPORTED=true CELLULOID_TASK_CLASS=Threaded @@ -28,7 +27,6 @@ env: matrix: - CELLULOID_BACKPORTED=true - CELLULOID_BACKPORTED=false - - CELLULOID_BACKPORTED=false CELLULOID_LEAKTEST=1 - CELLULOID_BACKPORTED=false CELLULOID_TASK_CLASS=Threaded - CELLULOID_BACKPORTED=true CELLULOID_TASK_CLASS=Threaded diff --git a/CHANGES.md b/CHANGES.md index 817cc6d..ac5ed3a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,4 @@ -0.17.2 (2015-09-28) +0.17.2 (2015-09-30) ----- * Revamped test suite, using shared RSpec configuration layer provided by Celluloid itself. * Updated gem dependencies provided by Celluloid::Sync... extraneous gems removed, or marked as development dependencies. From 14589c1751f539a9de1e339041ad1a0a3706245f Mon Sep 17 00:00:00 2001 From: //de Date: Wed, 30 Sep 2015 12:47:48 -0700 Subject: [PATCH 80/97] catch RBX failover all the way to IPv6 --- spec/celluloid/io/dns_resolver_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/celluloid/io/dns_resolver_spec.rb b/spec/celluloid/io/dns_resolver_spec.rb index 81c13b6..ab1d4f4 100644 --- a/spec/celluloid/io/dns_resolver_spec.rb +++ b/spec/celluloid/io/dns_resolver_spec.rb @@ -7,12 +7,12 @@ # disabled, thus .nameservers would return nil expect(Celluloid::IO::DNSResolver).to receive(:nameservers).at_most(:once) { nil } resolver = Celluloid::IO::DNSResolver.new - expect(resolver.resolve("localhost")).to eq Resolv::IPv4.create("127.0.0.1") + expect(resolver.resolve("localhost")).to eq(Resolv::IPv4.create("127.0.0.1")).or eq(Resolv::IPv6.create("::1")) end it "resolves hostnames" do resolver = Celluloid::IO::DNSResolver.new - expect(resolver.resolve("localhost")).to eq Resolv::IPv4.create("127.0.0.1") + expect(resolver.resolve("localhost")).to eq(Resolv::IPv4.create("127.0.0.1")).or eq(Resolv::IPv6.create("::1")) end it "resolves domain names" do From d94f43fdcaea3e05c16e44487b4fe81ce4f243b9 Mon Sep 17 00:00:00 2001 From: Ross Attrill Date: Tue, 6 Oct 2015 15:33:09 +1100 Subject: [PATCH 81/97] Only close Selector it not already closed Refer issue: https://github.com/celluloid/reel/issues/210 --- lib/celluloid/io/reactor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/celluloid/io/reactor.rb b/lib/celluloid/io/reactor.rb index 9be8ebc..11278ea 100644 --- a/lib/celluloid/io/reactor.rb +++ b/lib/celluloid/io/reactor.rb @@ -49,7 +49,7 @@ def wait(io, set) # have woken up. However, in some cases, the monitor is already # invalid, e.g. in the case that we are terminating. We catch this # case explicitly. - monitor.close + monitor.close unless monitor.closed? end end From fc678d3b57c2314b4cf254f979d0c73824a0e10e Mon Sep 17 00:00:00 2001 From: Hannes Georg Date: Sun, 1 Nov 2015 20:27:12 +0100 Subject: [PATCH 82/97] Added spec for TCPSocket#close to test if it flushes its write buffer. --- spec/celluloid/io/tcp_socket_spec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/spec/celluloid/io/tcp_socket_spec.rb b/spec/celluloid/io/tcp_socket_spec.rb index ee87912..aaba86f 100644 --- a/spec/celluloid/io/tcp_socket_spec.rb +++ b/spec/celluloid/io/tcp_socket_spec.rb @@ -181,6 +181,20 @@ end end end + + context "close" do + + it "flushes remaining data" do + with_connected_sockets(example_port) do |subject, peer| + subject.sync = false + within_io_actor { subject << payload } + expect{ peer.read_nonblock payload.length }.to raise_exception ::IO::WaitReadable + within_io_actor { subject.close } + expect(peer.read).to eq payload + end + end + + end end context "outside Celluloid::IO" do From d2791a9d99180bc4416ca8cf621d778453afe286 Mon Sep 17 00:00:00 2001 From: Hannes Georg Date: Sun, 1 Nov 2015 20:34:40 +0100 Subject: [PATCH 83/97] Don't delegate #close in Stream subclasses. Fix Stream#close. This fixes an error revealed in commit fc678d3b57c2314b4cf254f979d0c73824a0e10e. --- lib/celluloid/io/ssl_socket.rb | 1 - lib/celluloid/io/stream.rb | 2 +- lib/celluloid/io/tcp_socket.rb | 2 +- lib/celluloid/io/unix_socket.rb | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/celluloid/io/ssl_socket.rb b/lib/celluloid/io/ssl_socket.rb index 686da0a..1599f8a 100644 --- a/lib/celluloid/io/ssl_socket.rb +++ b/lib/celluloid/io/ssl_socket.rb @@ -9,7 +9,6 @@ class SSLSocket < Stream def_delegators :@socket, :read_nonblock, :write_nonblock, - :close, :closed?, :cert, :cipher, diff --git a/lib/celluloid/io/stream.rb b/lib/celluloid/io/stream.rb index 9921b6d..71e405a 100644 --- a/lib/celluloid/io/stream.rb +++ b/lib/celluloid/io/stream.rb @@ -309,7 +309,7 @@ def flush # Closes the stream and flushes any unwritten data. def close flush rescue nil - sysclose + to_io.close end ####### diff --git a/lib/celluloid/io/tcp_socket.rb b/lib/celluloid/io/tcp_socket.rb index 273a168..e9ffc71 100644 --- a/lib/celluloid/io/tcp_socket.rb +++ b/lib/celluloid/io/tcp_socket.rb @@ -7,7 +7,7 @@ module IO class TCPSocket < Stream extend Forwardable - def_delegators :@socket, :read_nonblock, :write_nonblock, :close, :close_read, :close_write, :closed? + def_delegators :@socket, :read_nonblock, :write_nonblock, :close_read, :close_write, :closed? def_delegators :@socket, :addr, :peeraddr, :setsockopt, :getsockname # Open a TCP socket, yielding it to the given block and closing it diff --git a/lib/celluloid/io/unix_socket.rb b/lib/celluloid/io/unix_socket.rb index 262f946..e5a9513 100644 --- a/lib/celluloid/io/unix_socket.rb +++ b/lib/celluloid/io/unix_socket.rb @@ -6,7 +6,7 @@ module IO class UNIXSocket < Stream extend Forwardable - def_delegators :@socket, :read_nonblock, :write_nonblock, :close, :closed?, :readline, :puts, :addr + def_delegators :@socket, :read_nonblock, :write_nonblock, :closed?, :readline, :puts, :addr # Open a UNIX connection. def self.open(socket_path, &block) From 35988d057cf03f7147bcc02ad0dfdb213f0a5e82 Mon Sep 17 00:00:00 2001 From: Hannes Georg Date: Sat, 7 Nov 2015 21:57:51 +0100 Subject: [PATCH 84/97] Use unix sockets in unix spec instead of tcp sockets. --- spec/celluloid/io/unix_socket_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index 038be15..7f3ad13 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -102,7 +102,7 @@ context "eof?" do it "blocks actor then returns by close" do - with_connected_sockets(example_port) do |subject, peer| + with_connected_unix_sockets do |subject, peer| started_at = Time.now Thread.new { sleep 0.5; peer.close; } within_io_actor { subject.eof? } @@ -112,7 +112,7 @@ it "blocks until gets the next byte" do allow(logger).to receive(:crash).with("Actor crashed!", Celluloid::TaskTimeout) - with_connected_sockets(example_port) do |subject, peer| + with_connected_unix_sockets do |subject, peer| peer << 0x00 peer.flush expect do From 19a45dc350603fb9a96b71425ce2b9c9d17e06c3 Mon Sep 17 00:00:00 2001 From: Hannes Georg Date: Sat, 7 Nov 2015 23:06:45 +0100 Subject: [PATCH 85/97] UNIXSocket: don't delegate #readline and #puts Delegating these two methods prevents them from using the internal buffers and therefore may lead to blocking IO and disordered bytes. --- lib/celluloid/io/unix_socket.rb | 2 +- spec/celluloid/io/unix_socket_spec.rb | 29 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/celluloid/io/unix_socket.rb b/lib/celluloid/io/unix_socket.rb index e5a9513..1d93696 100644 --- a/lib/celluloid/io/unix_socket.rb +++ b/lib/celluloid/io/unix_socket.rb @@ -6,7 +6,7 @@ module IO class UNIXSocket < Stream extend Forwardable - def_delegators :@socket, :read_nonblock, :write_nonblock, :closed?, :readline, :puts, :addr + def_delegators :@socket, :read_nonblock, :write_nonblock, :closed?, :addr # Open a UNIX connection. def self.open(socket_path, &block) diff --git a/spec/celluloid/io/unix_socket_spec.rb b/spec/celluloid/io/unix_socket_spec.rb index 038be15..d348aa6 100644 --- a/spec/celluloid/io/unix_socket_spec.rb +++ b/spec/celluloid/io/unix_socket_spec.rb @@ -171,4 +171,33 @@ end end end + + context 'puts' do + it 'uses the write buffer' do + with_connected_unix_sockets do |subject, peer| + subject.sync = false + subject << "a" + subject.puts "b" + subject << "c" + subject.flush + subject.close + expect(peer.read).to eq "ab\nc" + end + end + end + + context 'readline' do + it 'uses the read buffer' do + with_connected_unix_sockets do |subject, peer| + peer << "xline one\nline two\n" + subject.getc # read one character to fill buffer + Timeout::timeout(1){ + # this will block if the buffer is not used + expect(subject.readline).to eq "line one\n" + expect(subject.readline).to eq "line two\n" + } + end + end + end + end From 6bdde40fd68401fcf2d3b0b34f3a6bcf43e299ec Mon Sep 17 00:00:00 2001 From: Hannes Georg Date: Mon, 9 Nov 2015 15:42:06 +0100 Subject: [PATCH 86/97] Use a common super class for all socket wrappers The new superclass is called Celluloid::IO::Socket and essentialy deduplicates all #to_io methods and many delegates. This allows all socket wrappers to be created from a raw ruby socket using their default initializer or the new C::IO::Socket.try_convert method. --- lib/celluloid/io.rb | 1 + lib/celluloid/io/socket.rb | 80 ++++++++++++++ lib/celluloid/io/ssl_server.rb | 5 +- lib/celluloid/io/ssl_socket.rb | 18 ++-- lib/celluloid/io/stream.rb | 7 +- lib/celluloid/io/tcp_server.rb | 43 +++++--- lib/celluloid/io/tcp_socket.rb | 110 ++++++++++++-------- lib/celluloid/io/udp_socket.rb | 31 ++++-- lib/celluloid/io/unix_server.rb | 42 +++++--- lib/celluloid/io/unix_socket.rb | 20 ++-- spec/celluloid/io/socket_spec.rb | 173 +++++++++++++++++++++++++++++++ 11 files changed, 413 insertions(+), 117 deletions(-) create mode 100644 lib/celluloid/io/socket.rb create mode 100644 spec/celluloid/io/socket_spec.rb diff --git a/lib/celluloid/io.rb b/lib/celluloid/io.rb index ddb9960..044ae11 100644 --- a/lib/celluloid/io.rb +++ b/lib/celluloid/io.rb @@ -4,6 +4,7 @@ require "celluloid/io/dns_resolver" require "celluloid/io/mailbox" require "celluloid/io/reactor" +require "celluloid/io/socket" require "celluloid/io/stream" require "celluloid/io/tcp_server" diff --git a/lib/celluloid/io/socket.rb b/lib/celluloid/io/socket.rb new file mode 100644 index 0000000..1c48832 --- /dev/null +++ b/lib/celluloid/io/socket.rb @@ -0,0 +1,80 @@ +module Celluloid + module IO + # Base class for all classes that wrap a ruby socket. + # @abstract + class Socket + extend Forwardable + + def_delegators :@socket, :close, :close_read, :close_write, :closed? + def_delegators :@socket, :read_nonblock, :write_nonblock + def_delegators :@socket, :addr, :getsockopt, :setsockopt, :getsockname, :fcntl + + # @param socket [BasicSocket, OpenSSL::SSL::SSLSocket] + def initialize( socket ) + case( socket ) + when ::BasicSocket, OpenSSL::SSL::SSLSocket + @socket = socket + else + raise ArgumentError, "expected a socket, got #{socket.inspect}" + end + end + + # Returns the wrapped socket. + # @return [BasicSocket, OpenSSL::SSL::SSLSocket] + def to_io + @socket + end + + # Compatibility + Constants = ::Socket::Constants + include Constants + + # Celluloid::IO:Socket.new behaves like Socket.new for compatibility. + # This is is not problematic since Celluloid::IO::Socket is abstract. + # To instantiate a socket use one of its subclasses. + def self.new(*args) + if self == Celluloid::IO::Socket + return ::Socket.new(*args) + else + super + end + end + + # Tries to convert the given ruby socket into a subclass of GenericSocket. + # @param socket + # @return [SSLSocket, TCPServer, TCPSocket, UDPSocket, UNIXServer, UNIXSocket] + # @return [nil] if the socket can't be converted + def self.try_convert( socket, convert_io = true ) + case socket + when Celluloid::IO::Socket, Celluloid::IO::SSLServer then + socket + when ::TCPServer then + TCPServer.new(socket) + when ::TCPSocket then + TCPSocket.new(socket) + when ::UDPSocket then + UDPSocket.new(socket) + when ::UNIXServer then + UNIXServer.new(socket) + when ::UNIXSocket then + UNIXSocket.new(socket) + when OpenSSL::SSL::SSLServer + SSLServer.new(socket.to_io, socket.instance_variable_get(:@ctx)) + when OpenSSL::SSL::SSLSocket + SSLSocket.new(socket) + else + if convert_io + return try_convert( IO.try_convert(socket), false ) + end + nil + end + end + + class << self + extend Forwardable + def_delegators '::Socket', *(::Socket.methods - self.methods - [:try_convert]) + end + + end + end +end diff --git a/lib/celluloid/io/ssl_server.rb b/lib/celluloid/io/ssl_server.rb index 5d313d0..a7b0657 100644 --- a/lib/celluloid/io/ssl_server.rb +++ b/lib/celluloid/io/ssl_server.rb @@ -11,10 +11,7 @@ class SSLServer attr_reader :tcp_server def initialize(server, ctx) - if server.is_a?(::TCPServer) - server = Celluloid::IO::TCPServer.from_ruby_server(server) - end - @tcp_server = server + @tcp_server = Socket.try_convert(server) @ctx = ctx @start_immediately = true end diff --git a/lib/celluloid/io/ssl_socket.rb b/lib/celluloid/io/ssl_socket.rb index 1599f8a..c2966b2 100644 --- a/lib/celluloid/io/ssl_socket.rb +++ b/lib/celluloid/io/ssl_socket.rb @@ -6,10 +6,7 @@ module IO class SSLSocket < Stream extend Forwardable - def_delegators :@socket, - :read_nonblock, - :write_nonblock, - :closed?, + def_delegators :to_io, :cert, :cipher, :client_ca, @@ -21,14 +18,14 @@ class SSLSocket < Stream :sync_close= def initialize(io, ctx = OpenSSL::SSL::SSLContext.new) - super() @context = ctx - @socket = OpenSSL::SSL::SSLSocket.new(::IO.try_convert(io), @context) - @socket.sync_close = true if @socket.respond_to?(:sync_close=) + socket = OpenSSL::SSL::SSLSocket.new(::IO.try_convert(io), @context) + socket.sync_close = true if socket.respond_to?(:sync_close=) + super( socket ) end def connect - @socket.connect_nonblock + to_io.connect_nonblock self rescue ::IO::WaitReadable wait_readable @@ -36,7 +33,7 @@ def connect end def accept - @socket.accept_nonblock + to_io.accept_nonblock self rescue ::IO::WaitReadable wait_readable @@ -46,9 +43,6 @@ def accept retry end - def to_io - @socket - end end end end diff --git a/lib/celluloid/io/stream.rb b/lib/celluloid/io/stream.rb index 71e405a..e3f401b 100644 --- a/lib/celluloid/io/stream.rb +++ b/lib/celluloid/io/stream.rb @@ -8,7 +8,7 @@ module Celluloid module IO # Base class of all streams in Celluloid::IO - class Stream + class Stream < Socket include Enumerable # The "sync mode" of the stream @@ -16,7 +16,8 @@ class Stream # See IO#sync for full details. attr_accessor :sync - def initialize + def initialize( socket ) + super @eof = false @sync = true @read_buffer = ''.force_encoding(Encoding::ASCII_8BIT) @@ -309,7 +310,7 @@ def flush # Closes the stream and flushes any unwritten data. def close flush rescue nil - to_io.close + super end ####### diff --git a/lib/celluloid/io/tcp_server.rb b/lib/celluloid/io/tcp_server.rb index 40ca5b3..df5f08d 100644 --- a/lib/celluloid/io/tcp_server.rb +++ b/lib/celluloid/io/tcp_server.rb @@ -3,36 +3,49 @@ module Celluloid module IO # TCPServer with combined blocking and evented support - class TCPServer + class TCPServer < Socket extend Forwardable - def_delegators :@server, :listen, :sysaccept, :close, :closed?, :addr, :setsockopt + def_delegators :to_io, :listen, :sysaccept, :addr - def initialize(hostname_or_port, port = nil) - if port.nil? - @server = ::TCPServer.new(hostname_or_port) + # @overload initialize( port ) + # Opens a tcp server on the given port. + # @param port [Numeric] + # + # @overload initialize( hostname, port ) + # Opens a tcp server on the given port and interface. + # @param hostname [String] + # @param port [Numeric] + # + # @overload initialize( socket ) + # Wraps an already existing tcp server instance. + # @param socket [::TCPServer] + def initialize(*args) + if args.first.kind_of? ::BasicSocket + # socket + socket = args.first + fail ArgumentError, "wrong number of arguments (#{args.size} for 1)" if args.size != 1 + fail ArgumentError, "wrong kind of socket (#{socket.class} for TCPServer)" unless socket.kind_of? ::TCPServer + super( socket ) else - @server = ::TCPServer.new(hostname_or_port, port) + super( ::TCPServer.new(*args) ) end end + # @return [TCPSocket] def accept - Celluloid::IO.wait_readable(@server) + Celluloid::IO.wait_readable(to_io) accept_nonblock end + # @return [TCPSocket] def accept_nonblock - Celluloid::IO::TCPSocket.new(@server.accept_nonblock) - end - - def to_io - @server + Celluloid::IO::TCPSocket.new(to_io.accept_nonblock) end # Convert a Ruby TCPServer into a Celluloid::IO::TCPServer + # @deprecated Use .new instead. def self.from_ruby_server(ruby_server) - server = allocate - server.instance_variable_set(:@server, ruby_server) - server + new(ruby_server) end end end diff --git a/lib/celluloid/io/tcp_socket.rb b/lib/celluloid/io/tcp_socket.rb index e9ffc71..7668073 100644 --- a/lib/celluloid/io/tcp_socket.rb +++ b/lib/celluloid/io/tcp_socket.rb @@ -7,8 +7,7 @@ module IO class TCPSocket < Stream extend Forwardable - def_delegators :@socket, :read_nonblock, :write_nonblock, :close_read, :close_write, :closed? - def_delegators :@socket, :addr, :peeraddr, :setsockopt, :getsockname + def_delegators :to_io, :peeraddr # Open a TCP socket, yielding it to the given block and closing it # automatically when done (if a block is given) @@ -25,91 +24,114 @@ def self.open(*args, &_block) # Convert a Ruby TCPSocket into a Celluloid::IO::TCPSocket # DEPRECATED: to be removed in a future release + # @deprecated Use {Celluloid::IO::TCPSocket#new} instead. def self.from_ruby_socket(ruby_socket) new(ruby_socket) end - # Opens a TCP connection to remote_host on remote_port. If local_host - # and local_port are specified, then those parameters are used on the - # local end to establish the connection. - def initialize(remote_host, remote_port = nil, local_host = nil, local_port = nil) - super() - - # Allow users to pass in a Ruby TCPSocket directly - if remote_host.is_a? ::TCPSocket - @addr = nil - @socket = remote_host - return - elsif remote_port.nil? - fail ArgumentError, "wrong number of arguments (1 for 2)" + # @overload initialize( remote_host, remote_port = nil, local_host = nil, local_port = nil ) + # Opens a TCP connection to remote_host on remote_port. If local_host + # and local_port are specified, then those parameters are used on the + # local end to establish the connection. + # @param remote_host [String, Resolv::IPv4, Resolv::IPv6] + # @param remote_port [Numeric] + # @param local_host [String] + # @param local_port [Numeric] + # + # @overload initialize( socket ) + # Wraps an already existing tcp socket. + # @param socket [::TCPSocket] + # + def initialize(*args) + if args.first.kind_of? ::BasicSocket + # socket + socket = args.first + fail ArgumentError, "wrong number of arguments (#{args.size} for 1)" if args.size != 1 + fail ArgumentError, "wrong kind of socket (#{socket.class} for TCPSocket)" unless socket.kind_of? ::TCPSocket + super( socket ) + else + super( create_socket(*args) ) end + end + + # Receives a message + def recv(maxlen, flags = nil) + fail NotImplementedError, "flags not supported" if flags && !flags.zero? + readpartial(maxlen) + end + + # Send a message + def send(msg, flags, dest_sockaddr = nil) + fail NotImplementedError, "dest_sockaddr not supported" if dest_sockaddr + fail NotImplementedError, "flags not supported" unless flags.zero? + write(msg) + end + + # @return [Resolv::IPv4, Resolv::IPv6] + def addr + socket = to_io + ra = socket.remote_address + if ra.ipv4? + return Resolv::IPv4.create(ra.ip_address) + elsif ra.ipv6? + return Resolv::IPv6.create(ra.ip_address) + else + raise ArgumentError, "not an ip socket: #{socket.inspect}" + end + end + private + def create_socket(remote_host, remote_port = nil, local_host = nil, local_port = nil) # Is it an IPv4 address? begin - @addr = Resolv::IPv4.create(remote_host) + addr = Resolv::IPv4.create(remote_host) rescue ArgumentError end # Guess it's not IPv4! Is it IPv6? - unless @addr + unless addr begin - @addr = Resolv::IPv6.create(remote_host) + addr = Resolv::IPv6.create(remote_host) rescue ArgumentError end end # Guess it's not an IP address, so let's try DNS - unless @addr + unless addr addrs = Array(DNSResolver.new.resolve(remote_host)) fail Resolv::ResolvError, "DNS result has no information for #{remote_host}" if addrs.empty? # Pseudorandom round-robin DNS support :/ - @addr = addrs[rand(addrs.size)] + addr = addrs[rand(addrs.size)] end - case @addr + case addr when Resolv::IPv4 family = Socket::AF_INET when Resolv::IPv6 family = Socket::AF_INET6 - else fail ArgumentError, "unsupported address class: #{@addr.class}" + else fail ArgumentError, "unsupported address class: #{addr.class}" end - @socket = Socket.new(family, Socket::SOCK_STREAM, 0) - @socket.bind Addrinfo.tcp(local_host, local_port) if local_host + socket = Socket.new(family, Socket::SOCK_STREAM, 0) + socket.bind Addrinfo.tcp(local_host, local_port) if local_host begin - @socket.connect_nonblock Socket.sockaddr_in(remote_port, @addr.to_s) + socket.connect_nonblock Socket.sockaddr_in(remote_port, addr.to_s) rescue Errno::EINPROGRESS, Errno::EALREADY # JRuby raises EINPROGRESS, MRI raises EALREADY - - wait_writable + Celluloid::IO.wait_writable(socket) # HAX: for some reason we need to finish_connect ourselves on JRuby # This logic is unnecessary but JRuby still throws Errno::EINPROGRESS # if we retry the non-blocking connect instead of just finishing it - retry unless RUBY_PLATFORM == "java" && @socket.to_channel.finish_connect + retry unless RUBY_PLATFORM == "java" && socket.to_channel.finish_connect rescue Errno::EISCONN # We're now connected! Yay exceptions for flow control # NOTE: This is the approach the Ruby stdlib docs suggest ;_; end - end - - def to_io - @socket - end - - # Receives a message - def recv(maxlen, flags = nil) - fail NotImplementedError, "flags not supported" if flags && !flags.zero? - readpartial(maxlen) - end - # Send a message - def send(msg, flags, dest_sockaddr = nil) - fail NotImplementedError, "dest_sockaddr not supported" if dest_sockaddr - fail NotImplementedError, "flags not supported" unless flags.zero? - write(msg) + return socket end end end diff --git a/lib/celluloid/io/udp_socket.rb b/lib/celluloid/io/udp_socket.rb index 290655e..90bded6 100644 --- a/lib/celluloid/io/udp_socket.rb +++ b/lib/celluloid/io/udp_socket.rb @@ -1,12 +1,27 @@ module Celluloid module IO # UDPSockets with combined blocking and evented support - class UDPSocket + class UDPSocket < Socket extend Forwardable - def_delegators :@socket, :addr, :bind, :connect, :send, :recvfrom_nonblock, :close, :closed? + def_delegators :to_io, :bind, :connect, :send, :recvfrom_nonblock - def initialize(address_family = ::Socket::AF_INET) - @socket = ::UDPSocket.new(address_family) + # @overload initialize( address_family ) + # Opens a new udp socket using address_family. + # @param address_family [Numeric] + # + # @overload initialize( socket ) + # Wraps an already existing udp socket. + # @param socket [::UDPSocket] + def initialize(*args) + if args.first.kind_of? ::BasicSocket + # socket + socket = args.first + fail ArgumentError, "wrong number of arguments (#{args.size} for 1)" if args.size != 1 + fail ArgumentError, "wrong kind of socket (#{socket.class} for UDPSocket)" unless socket.kind_of? ::UDPSocket + super( socket ) + else + super( ::UDPSocket.new(*args) ) + end end # Wait until the socket is readable @@ -18,11 +33,12 @@ def wait_readable; Celluloid::IO.wait_readable(self); end # protocol-specific address information of the sender. def recvfrom(maxlen, flags = nil) begin - if @socket.respond_to? :recvfrom_nonblock - @socket.recvfrom_nonblock(maxlen, flags) + socket = to_io + if socket.respond_to? :recvfrom_nonblock + socket.recvfrom_nonblock(maxlen, flags) else # FIXME: hax for JRuby - @socket.recvfrom(maxlen, flags) + socket.recvfrom(maxlen, flags) end rescue ::IO::WaitReadable wait_readable @@ -30,7 +46,6 @@ def recvfrom(maxlen, flags = nil) end end - def to_io; @socket; end end end end diff --git a/lib/celluloid/io/unix_server.rb b/lib/celluloid/io/unix_server.rb index 53b71cf..f3306ed 100644 --- a/lib/celluloid/io/unix_server.rb +++ b/lib/celluloid/io/unix_server.rb @@ -3,40 +3,48 @@ module Celluloid module IO # UNIXServer with combined blocking and evented support - class UNIXServer + class UNIXServer < Socket extend Forwardable - def_delegators :@server, :listen, :sysaccept, :close, :closed? + def_delegators :to_io, :listen, :sysaccept def self.open(socket_path) self.new(socket_path) end - def initialize(socket_path) - begin - @server = ::UNIXServer.new(socket_path) - rescue => ex - # Translate the EADDRINUSE jRuby exception. - raise unless RUBY_PLATFORM == 'java' - if ex.class.name == "IOError" && # Won't agree to .is_a?(IOError) - ex.message.include?("in use") - raise Errno::EADDRINUSE.new(ex.message) + # @overload initialize( socket_path ) + # @param socket_path [String] + # + # @overload initialize( socket ) + # @param socket [::UNIXServer] + def initialize(socket) + if socket.kind_of? ::BasicSocket + # socket + fail ArgumentError, "wrong kind of socket (#{socket.class} for UNIXServer)" unless socket.kind_of? ::UNIXServer + super( socket ) + else + begin + super( ::UNIXServer.new(socket) ) + rescue => ex + # Translate the EADDRINUSE jRuby exception. + raise unless RUBY_PLATFORM == 'java' + if ex.class.name == "IOError" && # Won't agree to .is_a?(IOError) + ex.message.include?("in use") + raise Errno::EADDRINUSE.new(ex.message) + end + raise end - raise end end def accept - Celluloid::IO.wait_readable(@server) + Celluloid::IO.wait_readable(to_io) accept_nonblock end def accept_nonblock - Celluloid::IO::UNIXSocket.new(@server.accept_nonblock) + Celluloid::IO::UNIXSocket.new(to_io.accept_nonblock) end - def to_io - @server - end end end end diff --git a/lib/celluloid/io/unix_socket.rb b/lib/celluloid/io/unix_socket.rb index 1d93696..2205924 100644 --- a/lib/celluloid/io/unix_socket.rb +++ b/lib/celluloid/io/unix_socket.rb @@ -4,10 +4,6 @@ module Celluloid module IO # UNIXSocket with combined blocking and evented support class UNIXSocket < Stream - extend Forwardable - - def_delegators :@socket, :read_nonblock, :write_nonblock, :closed?, :addr - # Open a UNIX connection. def self.open(socket_path, &block) new(socket_path, &block) @@ -15,31 +11,27 @@ def self.open(socket_path, &block) # Convert a Ruby UNIXSocket into a Celluloid::IO::UNIXSocket # DEPRECATED: to be removed in a future release + # @deprecated use .new instead def self.from_ruby_socket(ruby_socket) new(ruby_socket) end # Open a UNIX connection. def initialize(socket_path, &block) - super() - # Allow users to pass in a Ruby UNIXSocket directly if socket_path.is_a? ::UNIXSocket - @socket = socket_path + super( socket_path ) return end # FIXME: not doing non-blocking connect - @socket = if block - ::UNIXSocket.open(socket_path, &block) - else - ::UNIXSocket.new(socket_path) + if block + super ::UNIXSocket.open(socket_path, &block) + else + super ::UNIXSocket.new(socket_path) end end - def to_io - @socket - end end end end diff --git a/spec/celluloid/io/socket_spec.rb b/spec/celluloid/io/socket_spec.rb new file mode 100644 index 0000000..239c6aa --- /dev/null +++ b/spec/celluloid/io/socket_spec.rb @@ -0,0 +1,173 @@ +require "spec_helper" + +RSpec.describe Celluloid::IO::Socket, library: :IO do + let(:logger) { Specs::FakeLogger.current } + let(:example_port) { assign_port } + + context '.try_convert' do + + subject{ described_class.try_convert(socket) } + + after(:each) do + if subject.respond_to? :close + subject.close + else + socket.close if socket.respond_to? :close + end + end + + context 'with a Celluloid Socket' do + let(:socket){ Celluloid::IO::UDPSocket.new } + + it 'returns given socket' do + expect(subject).to be socket + end + end + + context 'with a ::TCPServer' do + let(:socket){ ::TCPServer.new(example_port) } + + it 'creates a Celluloid::IO::TCPServer' do + expect(subject).to be_a Celluloid::IO::TCPServer + end + end + + context 'with a ::TCPSocket' do + let!(:server){ + ::TCPServer.new example_addr, example_port + } + after(:each){ + server.close + } + + let(:socket){ + ::TCPSocket.new example_addr, example_port + } + + it 'creates a Celluloid::IO::TCPSocket' do + expect(subject).to be_a Celluloid::IO::TCPSocket + end + end + + context 'with a ::UDPSocket' do + let(:socket){ ::UDPSocket.new } + + it 'creates a Celluloid::IO::UDPServer' do + expect(subject).to be_a Celluloid::IO::UDPSocket + end + end + + context 'with a ::UNIXServer' do + let(:socket){ ::UNIXServer.new(example_unix_sock) } + + it 'creates a Celluloid::IO::UNIXServer' do + expect(subject).to be_a Celluloid::IO::UNIXServer + end + end + + context 'with a ::UNIXSocket' do + let!(:server){ + ::UNIXServer.new(example_unix_sock) + } + after(:each){ + server.close + } + + let(:socket){ + ::UNIXSocket.new example_unix_sock + } + + it 'creates a Celluloid::IO::UNIXSocket' do + expect(subject).to be_a Celluloid::IO::UNIXSocket + end + end + + context 'with an OpenSSL::SSL::SSLServer' do + let(:socket){ + OpenSSL::SSL::SSLServer.new(::TCPServer.new(example_addr, example_port), OpenSSL::SSL::SSLContext.new) + } + + it 'creates a Celluloid::IO::SSLServer' do + expect(subject).to be_a Celluloid::IO::SSLServer + end + end + + context 'with an OpenSSL::SSL::SSLSocket' do + let!(:server){ + OpenSSL::SSL::SSLServer.new(::TCPServer.new(example_addr, example_port), OpenSSL::SSL::SSLContext.new) + } + after(:each){ + server.close + } + + let(:socket){ + OpenSSL::SSL::SSLSocket.new(::TCPSocket.new(example_addr, example_port)) + } + + it 'creates a Celluloid::IO::SSLSocket' do + expect(subject).to be_a Celluloid::IO::SSLSocket + end + end + + context 'with an object responding to #to_io' do + let(:real){ + ::UDPSocket.new + } + + let(:socket){ + proxy = double(:socket) + allow(proxy).to receive(:to_io){ real } + allow(proxy).to receive(:close){ real.close } + proxy + } + + it 'creates a celluloid socket' do + expect(subject).to be_a described_class + end + + it 'uses the returned IO' do + expect(subject.to_io).to be socket.to_io + end + end + + context 'with a simple object' do + let(:socket){ Object.new } + + it 'returns nil' do + expect(subject).to be_nil + end + end + end + + context 'compatibility with ::Socket' do + + context '.new' do + it "creates basic sockets" do + socket = Celluloid::IO::Socket.new( Celluloid::IO::Socket::AF_INET, Celluloid::IO::Socket::SOCK_STREAM, 0 ) + expect( socket ).to be_a ::Socket + socket.close + end + end + + context '.pair' do + it "creates basic sockets" do + a,b = Celluloid::IO::Socket.pair( Celluloid::IO::Socket::AF_UNIX, Celluloid::IO::Socket::SOCK_DGRAM, 0) + expect( a ).to be_a ::Socket + expect( b ).to be_a ::Socket + a.close + b.close + end + end + + context '.for_fd' do + it "creates basic sockets" do + socket = Celluloid::IO::Socket.new( Celluloid::IO::Socket::AF_INET, Celluloid::IO::Socket::SOCK_STREAM, 0 ) + copy = Celluloid::IO::Socket.for_fd( socket.fileno ) + expect( copy ).to be_a ::Socket + copy.close + end + end + + end + +end From e44c7ab5eeb015bd81c5269db478f4773ffed831 Mon Sep 17 00:00:00 2001 From: Tiago Cardoso Date: Thu, 13 Mar 2014 13:21:30 +0100 Subject: [PATCH 87/97] added failing spec which checks wether a socket is usable after a read operation timed out before --- spec/celluloid/io/actor_spec.rb | 52 ++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/spec/celluloid/io/actor_spec.rb b/spec/celluloid/io/actor_spec.rb index e01fc7d..aa190c4 100644 --- a/spec/celluloid/io/actor_spec.rb +++ b/spec/celluloid/io/actor_spec.rb @@ -1,5 +1,55 @@ require "spec_helper" RSpec.describe Celluloid::IO, library: :IO do - it_behaves_like "a Celluloid Actor", Celluloid::IO + it_behaves_like "a Celluloid Actor", Celluloid::IO do + context :timeouts do + let :sleeping_actor_class do + Class.new do + include Celluloid::IO + def initialize + @server = Celluloid::IO::TCPServer.new(example_addr, example_port) + async { @server.accept ; sleep 10 } + end + end + end + let :foo_actor_class do + Class.new do + include Celluloid::IO + def initialize + @sock = Celluloid::IO::TCPSocket.new(example_addr, example_port) + end + + # returns true if the operation timedout + def timedout_read(duration) + begin + timeout(duration) do + @sock.wait_readable + end + rescue Celluloid::Task::TimeoutError + return true + end + false + end + + # returns true if it cannot write (socket is already registered) + def failed_write + begin + @sock.wait_readable + rescue ArgumentError # IO Selector Exception + return true + end + false + end + end + end + + it "frees up the socket when a timeout error occurs" do + a1 = sleeping_actor_class.new + a2 = foo_actor_class.new + + a2.timedout_read(1).should be_true # this ensures that the socket timeouted trying to read + a2.failed_write.should be_false # this ensures that the socket isn't usable anymore + end + end + end end From d9ba8de8a8c573044b962cf19f68ff21e12c92d2 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 7 Dec 2015 23:08:37 +1300 Subject: [PATCH 88/97] ExampleActor was removed. --- spec/celluloid/io/tcp_server_spec.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index 51f15aa..1cbf70b 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -29,7 +29,9 @@ end it "sends information to the client later" do - class LaterActor < ExampleActor + class LaterActor + include Celluloid::IO + def send_later(socket) peer = socket.accept after(0.4) { peer.write "1" } From f866331befd2576911bb0a0fb5b178f26b5cadfc Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Thu, 31 Dec 2015 00:25:12 +0900 Subject: [PATCH 89/97] Specify missing argument --- spec/celluloid/io/tcp_server_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index 1cbf70b..0d79894 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -39,7 +39,7 @@ def send_later(socket) peer end end - with_tcp_server do |subject| + with_tcp_server(example_port) do |subject| thread = Thread.new { TCPSocket.new(example_addr, example_port) } actor = LaterActor.new begin From f236821912619bbdac2c4711b70b2867499cfa20 Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Thu, 31 Dec 2015 00:29:07 +0900 Subject: [PATCH 90/97] Specify addr & port as arguments for test class To detect addr & port here, there should be passed as arguments. Because of here is a `Class.new` context, not a RSpec context. --- spec/celluloid/io/actor_spec.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/spec/celluloid/io/actor_spec.rb b/spec/celluloid/io/actor_spec.rb index aa190c4..cbbdea5 100644 --- a/spec/celluloid/io/actor_spec.rb +++ b/spec/celluloid/io/actor_spec.rb @@ -2,12 +2,14 @@ RSpec.describe Celluloid::IO, library: :IO do it_behaves_like "a Celluloid Actor", Celluloid::IO do + let(:example_port) { assign_port } + context :timeouts do let :sleeping_actor_class do Class.new do include Celluloid::IO - def initialize - @server = Celluloid::IO::TCPServer.new(example_addr, example_port) + def initialize(addr, port) + @server = Celluloid::IO::TCPServer.new(addr, port) async { @server.accept ; sleep 10 } end end @@ -15,8 +17,8 @@ def initialize let :foo_actor_class do Class.new do include Celluloid::IO - def initialize - @sock = Celluloid::IO::TCPSocket.new(example_addr, example_port) + def initialize(addr, port) + @sock = Celluloid::IO::TCPSocket.new(addr, port) end # returns true if the operation timedout @@ -44,8 +46,8 @@ def failed_write end it "frees up the socket when a timeout error occurs" do - a1 = sleeping_actor_class.new - a2 = foo_actor_class.new + a1 = sleeping_actor_class.new(example_addr, example_port) + a2 = foo_actor_class.new(example_addr, example_port) a2.timedout_read(1).should be_true # this ensures that the socket timeouted trying to read a2.failed_write.should be_false # this ensures that the socket isn't usable anymore From 02417177a1524263e515b5ec8130381fa462c4f5 Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Thu, 31 Dec 2015 01:14:03 +0900 Subject: [PATCH 91/97] Correct class name --- spec/celluloid/io/actor_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/celluloid/io/actor_spec.rb b/spec/celluloid/io/actor_spec.rb index cbbdea5..bf3973a 100644 --- a/spec/celluloid/io/actor_spec.rb +++ b/spec/celluloid/io/actor_spec.rb @@ -27,7 +27,7 @@ def timedout_read(duration) timeout(duration) do @sock.wait_readable end - rescue Celluloid::Task::TimeoutError + rescue Celluloid::TaskTimeout return true end false From a2d5d5ad29d15135f80502ced52e9fb03a599270 Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Thu, 31 Dec 2015 00:30:48 +0900 Subject: [PATCH 92/97] Use `expect` syntax instead of `should` one Current RSpec config doesn't define `should`. --- spec/celluloid/io/actor_spec.rb | 4 ++-- spec/celluloid/io/tcp_server_spec.rb | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/celluloid/io/actor_spec.rb b/spec/celluloid/io/actor_spec.rb index bf3973a..af16c67 100644 --- a/spec/celluloid/io/actor_spec.rb +++ b/spec/celluloid/io/actor_spec.rb @@ -49,8 +49,8 @@ def failed_write a1 = sleeping_actor_class.new(example_addr, example_port) a2 = foo_actor_class.new(example_addr, example_port) - a2.timedout_read(1).should be_true # this ensures that the socket timeouted trying to read - a2.failed_write.should be_false # this ensures that the socket isn't usable anymore + expect(a2.timedout_read(1)).to eq true # this ensures that the socket timeouted trying to read + expect(a2.failed_write).to eq false # this ensures that the socket isn't usable anymore end end end diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index 0d79894..afc0945 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -46,9 +46,9 @@ def send_later(socket) peer = actor.send_later(subject) client = thread.value client.write payload - peer.read(payload.size).should eq payload # confirm the client read - Timeout::timeout(1) { client.read(4).should eq "1" } - Timeout::timeout(2) { client.read(4).should eq "2" } + expect(peer.read(payload.size)).to eq payload # confirm the client read + Timeout::timeout(1) { expect(client.read(4)).to eq "1" } + Timeout::timeout(2) { expect(client.read(4)).to eq "2" } ensure actor.terminate if actor.alive? end From d3dd56b0a145388061a75818afcbe15193d4f2ed Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Thu, 31 Dec 2015 00:41:18 +0900 Subject: [PATCH 93/97] Correct read chunk size `4` is too large to read chunk, the each data is 1 byte. --- spec/celluloid/io/tcp_server_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/celluloid/io/tcp_server_spec.rb b/spec/celluloid/io/tcp_server_spec.rb index afc0945..c9b5168 100644 --- a/spec/celluloid/io/tcp_server_spec.rb +++ b/spec/celluloid/io/tcp_server_spec.rb @@ -47,8 +47,8 @@ def send_later(socket) client = thread.value client.write payload expect(peer.read(payload.size)).to eq payload # confirm the client read - Timeout::timeout(1) { expect(client.read(4)).to eq "1" } - Timeout::timeout(2) { expect(client.read(4)).to eq "2" } + Timeout::timeout(1) { expect(client.read(1)).to eq "1" } + Timeout::timeout(2) { expect(client.read(1)).to eq "2" } ensure actor.terminate if actor.alive? end From 8bf7f38e35bffc38cc69dedcb6ce9ec0fceee4c6 Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Thu, 31 Dec 2015 00:44:00 +0900 Subject: [PATCH 94/97] The flag for `UDPSpcket#recvfrom_nonblock` should be Numeric in Ruby 2.3 --- lib/celluloid/io/udp_socket.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/celluloid/io/udp_socket.rb b/lib/celluloid/io/udp_socket.rb index 290655e..703ab04 100644 --- a/lib/celluloid/io/udp_socket.rb +++ b/lib/celluloid/io/udp_socket.rb @@ -16,7 +16,7 @@ def wait_readable; Celluloid::IO.wait_readable(self); end # MSG_ options. The first element of the results, mesg, is the data # received. The second element, sender_addrinfo, contains # protocol-specific address information of the sender. - def recvfrom(maxlen, flags = nil) + def recvfrom(maxlen, flags = 0) begin if @socket.respond_to? :recvfrom_nonblock @socket.recvfrom_nonblock(maxlen, flags) From 82f446d6f080f51f65915a719dc18cdd1f122e09 Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Thu, 31 Dec 2015 00:46:35 +0900 Subject: [PATCH 95/97] Test against Ruby 2.3.0 on Travis CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5a569b2..0e86ba0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ language: ruby rvm: - rbx-2 - jruby + - 2.3.0 - 2.2.2 - 2.2.0 - 2.1.4 From a70f30bf79aa04385b6800c9e37b9898731e8ba6 Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Thu, 31 Dec 2015 05:08:07 +0900 Subject: [PATCH 96/97] This spec should be skipped because of failing spec --- spec/celluloid/io/actor_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/celluloid/io/actor_spec.rb b/spec/celluloid/io/actor_spec.rb index af16c67..656f239 100644 --- a/spec/celluloid/io/actor_spec.rb +++ b/spec/celluloid/io/actor_spec.rb @@ -37,7 +37,7 @@ def timedout_read(duration) def failed_write begin @sock.wait_readable - rescue ArgumentError # IO Selector Exception + rescue ArgumentError # IO Selector Exception return true end false @@ -50,6 +50,7 @@ def failed_write a2 = foo_actor_class.new(example_addr, example_port) expect(a2.timedout_read(1)).to eq true # this ensures that the socket timeouted trying to read + skip "not implemented" expect(a2.failed_write).to eq false # this ensures that the socket isn't usable anymore end end From 002de5eac524a70bfb676e2e3548c905090a9679 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 5 Jan 2016 19:08:31 +1300 Subject: [PATCH 97/97] Minor formatting changes to new socket code. --- lib/celluloid/io/socket.rb | 20 ++++++++++---------- lib/celluloid/io/ssl_socket.rb | 2 +- lib/celluloid/io/stream.rb | 2 +- lib/celluloid/io/tcp_server.rb | 14 ++++++++------ lib/celluloid/io/tcp_socket.rb | 8 ++++---- lib/celluloid/io/udp_socket.rb | 8 ++++---- lib/celluloid/io/unix_server.rb | 8 ++++---- lib/celluloid/io/unix_socket.rb | 2 +- spec/celluloid/io/socket_spec.rb | 14 +++++++------- 9 files changed, 40 insertions(+), 38 deletions(-) diff --git a/lib/celluloid/io/socket.rb b/lib/celluloid/io/socket.rb index 1c48832..9bd369a 100644 --- a/lib/celluloid/io/socket.rb +++ b/lib/celluloid/io/socket.rb @@ -10,8 +10,8 @@ class Socket def_delegators :@socket, :addr, :getsockopt, :setsockopt, :getsockname, :fcntl # @param socket [BasicSocket, OpenSSL::SSL::SSLSocket] - def initialize( socket ) - case( socket ) + def initialize(socket) + case socket when ::BasicSocket, OpenSSL::SSL::SSLSocket @socket = socket else @@ -44,19 +44,19 @@ def self.new(*args) # @param socket # @return [SSLSocket, TCPServer, TCPSocket, UDPSocket, UNIXServer, UNIXSocket] # @return [nil] if the socket can't be converted - def self.try_convert( socket, convert_io = true ) + def self.try_convert(socket, convert_io = true) case socket - when Celluloid::IO::Socket, Celluloid::IO::SSLServer then + when Celluloid::IO::Socket, Celluloid::IO::SSLServer socket - when ::TCPServer then + when ::TCPServer TCPServer.new(socket) - when ::TCPSocket then + when ::TCPSocket TCPSocket.new(socket) - when ::UDPSocket then + when ::UDPSocket UDPSocket.new(socket) - when ::UNIXServer then + when ::UNIXServer UNIXServer.new(socket) - when ::UNIXSocket then + when ::UNIXSocket UNIXSocket.new(socket) when OpenSSL::SSL::SSLServer SSLServer.new(socket.to_io, socket.instance_variable_get(:@ctx)) @@ -64,7 +64,7 @@ def self.try_convert( socket, convert_io = true ) SSLSocket.new(socket) else if convert_io - return try_convert( IO.try_convert(socket), false ) + return try_convert(IO.try_convert(socket), false) end nil end diff --git a/lib/celluloid/io/ssl_socket.rb b/lib/celluloid/io/ssl_socket.rb index c2966b2..6468313 100644 --- a/lib/celluloid/io/ssl_socket.rb +++ b/lib/celluloid/io/ssl_socket.rb @@ -21,7 +21,7 @@ def initialize(io, ctx = OpenSSL::SSL::SSLContext.new) @context = ctx socket = OpenSSL::SSL::SSLSocket.new(::IO.try_convert(io), @context) socket.sync_close = true if socket.respond_to?(:sync_close=) - super( socket ) + super(socket) end def connect diff --git a/lib/celluloid/io/stream.rb b/lib/celluloid/io/stream.rb index e3f401b..b9f6185 100644 --- a/lib/celluloid/io/stream.rb +++ b/lib/celluloid/io/stream.rb @@ -16,7 +16,7 @@ class Stream < Socket # See IO#sync for full details. attr_accessor :sync - def initialize( socket ) + def initialize(socket) super @eof = false @sync = true diff --git a/lib/celluloid/io/tcp_server.rb b/lib/celluloid/io/tcp_server.rb index df5f08d..e0e955a 100644 --- a/lib/celluloid/io/tcp_server.rb +++ b/lib/celluloid/io/tcp_server.rb @@ -7,16 +7,16 @@ class TCPServer < Socket extend Forwardable def_delegators :to_io, :listen, :sysaccept, :addr - # @overload initialize( port ) + # @overload initialize(port) # Opens a tcp server on the given port. # @param port [Numeric] # - # @overload initialize( hostname, port ) + # @overload initialize(hostname, port) # Opens a tcp server on the given port and interface. # @param hostname [String] # @param port [Numeric] # - # @overload initialize( socket ) + # @overload initialize(socket) # Wraps an already existing tcp server instance. # @param socket [::TCPServer] def initialize(*args) @@ -25,9 +25,9 @@ def initialize(*args) socket = args.first fail ArgumentError, "wrong number of arguments (#{args.size} for 1)" if args.size != 1 fail ArgumentError, "wrong kind of socket (#{socket.class} for TCPServer)" unless socket.kind_of? ::TCPServer - super( socket ) + super(socket) else - super( ::TCPServer.new(*args) ) + super(::TCPServer.new(*args)) end end @@ -45,7 +45,9 @@ def accept_nonblock # Convert a Ruby TCPServer into a Celluloid::IO::TCPServer # @deprecated Use .new instead. def self.from_ruby_server(ruby_server) - new(ruby_server) + warn "#from_ruby_server is deprecated please use .new instead" + + self.new(ruby_server) end end end diff --git a/lib/celluloid/io/tcp_socket.rb b/lib/celluloid/io/tcp_socket.rb index 7668073..8c64df3 100644 --- a/lib/celluloid/io/tcp_socket.rb +++ b/lib/celluloid/io/tcp_socket.rb @@ -29,7 +29,7 @@ def self.from_ruby_socket(ruby_socket) new(ruby_socket) end - # @overload initialize( remote_host, remote_port = nil, local_host = nil, local_port = nil ) + # @overload initialize(remote_host, remote_port = nil, local_host = nil, local_port = nil) # Opens a TCP connection to remote_host on remote_port. If local_host # and local_port are specified, then those parameters are used on the # local end to establish the connection. @@ -38,7 +38,7 @@ def self.from_ruby_socket(ruby_socket) # @param local_host [String] # @param local_port [Numeric] # - # @overload initialize( socket ) + # @overload initialize(socket) # Wraps an already existing tcp socket. # @param socket [::TCPSocket] # @@ -48,9 +48,9 @@ def initialize(*args) socket = args.first fail ArgumentError, "wrong number of arguments (#{args.size} for 1)" if args.size != 1 fail ArgumentError, "wrong kind of socket (#{socket.class} for TCPSocket)" unless socket.kind_of? ::TCPSocket - super( socket ) + super(socket) else - super( create_socket(*args) ) + super(create_socket(*args)) end end diff --git a/lib/celluloid/io/udp_socket.rb b/lib/celluloid/io/udp_socket.rb index 600d149..b2edc36 100644 --- a/lib/celluloid/io/udp_socket.rb +++ b/lib/celluloid/io/udp_socket.rb @@ -5,11 +5,11 @@ class UDPSocket < Socket extend Forwardable def_delegators :to_io, :bind, :connect, :send, :recvfrom_nonblock - # @overload initialize( address_family ) + # @overload initialize(address_family) # Opens a new udp socket using address_family. # @param address_family [Numeric] # - # @overload initialize( socket ) + # @overload initialize(socket) # Wraps an already existing udp socket. # @param socket [::UDPSocket] def initialize(*args) @@ -18,9 +18,9 @@ def initialize(*args) socket = args.first fail ArgumentError, "wrong number of arguments (#{args.size} for 1)" if args.size != 1 fail ArgumentError, "wrong kind of socket (#{socket.class} for UDPSocket)" unless socket.kind_of? ::UDPSocket - super( socket ) + super(socket) else - super( ::UDPSocket.new(*args) ) + super(::UDPSocket.new(*args)) end end diff --git a/lib/celluloid/io/unix_server.rb b/lib/celluloid/io/unix_server.rb index f3306ed..831e74b 100644 --- a/lib/celluloid/io/unix_server.rb +++ b/lib/celluloid/io/unix_server.rb @@ -11,19 +11,19 @@ def self.open(socket_path) self.new(socket_path) end - # @overload initialize( socket_path ) + # @overload initialize(socket_path) # @param socket_path [String] # - # @overload initialize( socket ) + # @overload initialize(socket) # @param socket [::UNIXServer] def initialize(socket) if socket.kind_of? ::BasicSocket # socket fail ArgumentError, "wrong kind of socket (#{socket.class} for UNIXServer)" unless socket.kind_of? ::UNIXServer - super( socket ) + super(socket) else begin - super( ::UNIXServer.new(socket) ) + super(::UNIXServer.new(socket)) rescue => ex # Translate the EADDRINUSE jRuby exception. raise unless RUBY_PLATFORM == 'java' diff --git a/lib/celluloid/io/unix_socket.rb b/lib/celluloid/io/unix_socket.rb index 2205924..7c20575 100644 --- a/lib/celluloid/io/unix_socket.rb +++ b/lib/celluloid/io/unix_socket.rb @@ -20,7 +20,7 @@ def self.from_ruby_socket(ruby_socket) def initialize(socket_path, &block) # Allow users to pass in a Ruby UNIXSocket directly if socket_path.is_a? ::UNIXSocket - super( socket_path ) + super(socket_path) return end diff --git a/spec/celluloid/io/socket_spec.rb b/spec/celluloid/io/socket_spec.rb index 239c6aa..5eb2608 100644 --- a/spec/celluloid/io/socket_spec.rb +++ b/spec/celluloid/io/socket_spec.rb @@ -143,8 +143,8 @@ context '.new' do it "creates basic sockets" do - socket = Celluloid::IO::Socket.new( Celluloid::IO::Socket::AF_INET, Celluloid::IO::Socket::SOCK_STREAM, 0 ) - expect( socket ).to be_a ::Socket + socket = Celluloid::IO::Socket.new(Celluloid::IO::Socket::AF_INET, Celluloid::IO::Socket::SOCK_STREAM, 0) + expect(socket).to be_a ::Socket socket.close end end @@ -152,8 +152,8 @@ context '.pair' do it "creates basic sockets" do a,b = Celluloid::IO::Socket.pair( Celluloid::IO::Socket::AF_UNIX, Celluloid::IO::Socket::SOCK_DGRAM, 0) - expect( a ).to be_a ::Socket - expect( b ).to be_a ::Socket + expect(a).to be_a ::Socket + expect(b).to be_a ::Socket a.close b.close end @@ -161,9 +161,9 @@ context '.for_fd' do it "creates basic sockets" do - socket = Celluloid::IO::Socket.new( Celluloid::IO::Socket::AF_INET, Celluloid::IO::Socket::SOCK_STREAM, 0 ) - copy = Celluloid::IO::Socket.for_fd( socket.fileno ) - expect( copy ).to be_a ::Socket + socket = Celluloid::IO::Socket.new(Celluloid::IO::Socket::AF_INET, Celluloid::IO::Socket::SOCK_STREAM, 0) + copy = Celluloid::IO::Socket.for_fd(socket.fileno) + expect(copy).to be_a ::Socket copy.close end end