cool.io 1.9.5 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yaml +1 -0
- data/.github/workflows/valgrind.yaml +0 -3
- data/Rakefile +1 -0
- data/ext/cool.io/buffer.c +32 -18
- data/ext/cool.io/ev_wrap.h +1 -0
- data/ext/cool.io/iowatcher.c +18 -1
- data/ext/cool.io/loop.c +6 -4
- data/ext/cool.io/stat_watcher.c +30 -18
- data/ext/cool.io/timer_watcher.c +1 -1
- data/ext/cool.io/watcher.h +0 -17
- data/ext/libev/ev.c +73 -11
- data/ext/libev/ev_vars.h +4 -0
- data/ext/libev/ev_win32_stat.c +851 -0
- data/ext/libev/ev_wrap.h +4 -0
- data/lib/cool.io/dns_resolver.rb +1 -0
- data/lib/cool.io/loop.rb +5 -1
- data/lib/cool.io/version.rb +1 -1
- data/spec/detach_race_condition_spec.rb +23 -11
- data/spec/dns_spec.rb +11 -0
- data/spec/fixtures/windows_stat_native.c +1305 -0
- data/spec/iobuffer_spec.rb +57 -1
- data/spec/loop_spec.rb +31 -0
- data/spec/stat_watcher_spec.rb +55 -0
- data/spec/tcp_server_spec.rb +6 -6
- data/spec/watcher_reattach_spec.rb +54 -0
- data/spec/windows_stat_native_spec.rb +193 -0
- data/spec/windows_stat_watcher_spec.rb +363 -0
- metadata +13 -2
data/ext/libev/ev_wrap.h
CHANGED
|
@@ -98,6 +98,8 @@
|
|
|
98
98
|
#define vec_ro ((loop)->vec_ro)
|
|
99
99
|
#define vec_wi ((loop)->vec_wi)
|
|
100
100
|
#define vec_wo ((loop)->vec_wo)
|
|
101
|
+
#define win32_fs ((loop)->win32_fs)
|
|
102
|
+
#define win32_fs_disabled ((loop)->win32_fs_disabled)
|
|
101
103
|
#else
|
|
102
104
|
#undef EV_WRAP_H
|
|
103
105
|
#undef acquire_cb
|
|
@@ -197,4 +199,6 @@
|
|
|
197
199
|
#undef vec_ro
|
|
198
200
|
#undef vec_wi
|
|
199
201
|
#undef vec_wo
|
|
202
|
+
#undef win32_fs
|
|
203
|
+
#undef win32_fs_disabled
|
|
200
204
|
#endif
|
data/lib/cool.io/dns_resolver.rb
CHANGED
|
@@ -218,6 +218,7 @@ module Coolio
|
|
|
218
218
|
while not message.empty?
|
|
219
219
|
type = message[2..3].unpack('n').first.to_i
|
|
220
220
|
rdlength = message[10..11].unpack('n').first.to_i
|
|
221
|
+
return if message.bytesize < 12 + rdlength
|
|
221
222
|
rdata = message[12..(12 + rdlength - 1)]
|
|
222
223
|
message.slice!(0, 12 + rdlength)
|
|
223
224
|
|
data/lib/cool.io/loop.rb
CHANGED
|
@@ -38,6 +38,10 @@ module Coolio
|
|
|
38
38
|
# :kqueue (BSD/Mac OS X)
|
|
39
39
|
# :port (Solaris 10)
|
|
40
40
|
#
|
|
41
|
+
# Raises RuntimeError if none of the selected backends is usable.
|
|
42
|
+
# Unless :skip_environment is true, $LIBEV_FLAGS can override the
|
|
43
|
+
# backend selection and cause the same error.
|
|
44
|
+
#
|
|
41
45
|
def initialize(options = {})
|
|
42
46
|
@watchers = {}
|
|
43
47
|
@active_watchers = 0
|
|
@@ -47,7 +51,7 @@ module Coolio
|
|
|
47
51
|
options.each do |option, value|
|
|
48
52
|
case option
|
|
49
53
|
when :skip_environment
|
|
50
|
-
flags |=
|
|
54
|
+
flags |= EVFLAG_NOENV if value
|
|
51
55
|
when :fork_check
|
|
52
56
|
flags |= EVFLAG_FORKCHECK if value
|
|
53
57
|
when :backend
|
data/lib/cool.io/version.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Cool.io::Loop do
|
|
4
|
-
# An IOWatcher that drains its
|
|
4
|
+
# An IOWatcher that drains its socket and then runs a user-supplied block,
|
|
5
5
|
# receiving itself as the argument.
|
|
6
6
|
class Victim < Cool.io::IOWatcher
|
|
7
7
|
def initialize(io, &on_readable)
|
|
@@ -34,16 +34,21 @@ describe Cool.io::Loop do
|
|
|
34
34
|
# crashed intermittently on macOS.
|
|
35
35
|
it "does not raise when a watcher with a pending event is detached during dispatch" do
|
|
36
36
|
iterations = 200
|
|
37
|
+
# Winsock select monitors sockets, not IO.pipe handles. TCP connections
|
|
38
|
+
# exercise the same queued-event scenario on every supported platform.
|
|
39
|
+
listener = TCPServer.new('127.0.0.1', 0)
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
watchers = []
|
|
41
|
+
iterations.times do
|
|
42
|
+
coolio_loop = Cool.io::Loop.new
|
|
43
|
+
connections = []
|
|
44
|
+
watchers = []
|
|
43
45
|
|
|
46
|
+
begin
|
|
44
47
|
5.times do
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
w = TCPSocket.new('127.0.0.1', listener.addr[1])
|
|
49
|
+
connections << [nil, w]
|
|
50
|
+
r = listener.accept
|
|
51
|
+
connections.last[0] = r
|
|
47
52
|
|
|
48
53
|
watcher = Victim.new(r) do |fired|
|
|
49
54
|
# Detach every other watcher whose event is already queued for this
|
|
@@ -58,16 +63,23 @@ describe Cool.io::Loop do
|
|
|
58
63
|
w.write("dummy\n") # make the read end readable so an event is pending
|
|
59
64
|
end
|
|
60
65
|
|
|
66
|
+
# TCP delivery is asynchronous. Ensure all five read ends are ready
|
|
67
|
+
# before libev collects the events, without consuming their data.
|
|
68
|
+
connections.each do |r, _|
|
|
69
|
+
expect(IO.select([r], nil, nil, 2)).not_to be_nil
|
|
70
|
+
end
|
|
61
71
|
coolio_loop.run_once
|
|
62
72
|
|
|
63
73
|
# Only the first dispatched watcher runs; it detaches the other four,
|
|
64
74
|
# whose pending events are then skipped.
|
|
65
75
|
expect(watchers.count(&:attached?)).to eq(1)
|
|
66
|
-
|
|
76
|
+
ensure
|
|
67
77
|
watchers.each { |watcher| watcher.detach if watcher.attached? }
|
|
68
|
-
|
|
78
|
+
connections.each { |r, w| r.close if r; w.close }
|
|
69
79
|
end
|
|
70
|
-
|
|
80
|
+
end
|
|
81
|
+
ensure
|
|
82
|
+
listener.close if listener
|
|
71
83
|
end
|
|
72
84
|
|
|
73
85
|
class HttpHandler < Coolio::IO
|
data/spec/dns_spec.rb
CHANGED
|
@@ -211,6 +211,17 @@ describe "DNS" do
|
|
|
211
211
|
resolver.__send__(:on_readable)
|
|
212
212
|
end
|
|
213
213
|
|
|
214
|
+
it "fails a response whose A record is shorter than its RDLENGTH instead of resolving a bogus address" do
|
|
215
|
+
truncated = dns_response_for(resolver, address: "1.2.3.4")[0...-4]
|
|
216
|
+
allow(resolver.instance_variable_get(:@socket)).to receive(:recvfrom_nonblock).and_return([truncated, sender])
|
|
217
|
+
|
|
218
|
+
expect(resolver).to_not receive(:on_success)
|
|
219
|
+
expect(resolver).to receive(:on_failure)
|
|
220
|
+
expect(resolver).to receive(:detach)
|
|
221
|
+
|
|
222
|
+
resolver.__send__(:on_readable)
|
|
223
|
+
end
|
|
224
|
+
|
|
214
225
|
it "ignores a spoofed response instead of resolving or failing it" do
|
|
215
226
|
forged = dns_response_for(resolver, address: "6.6.6.6")
|
|
216
227
|
allow(resolver.instance_variable_get(:@socket)).to receive(:recvfrom_nonblock)
|