yahns 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/GIT-VERSION-GEN +1 -1
- data/INSTALL +7 -0
- data/README +3 -3
- data/lib/yahns.rb +2 -2
- data/lib/yahns/queue_kqueue.rb +82 -0
- data/lib/yahns/queue_quitter_pipe.rb +2 -2
- data/lib/yahns/sendfile_compat.rb +29 -0
- data/lib/yahns/sigevent_pipe.rb +2 -2
- data/lib/yahns/wbuf.rb +14 -1
- data/lib/yahns/wbuf_common.rb +8 -2
- data/test/helper.rb +6 -0
- data/test/test_buffer_tmpdir.rb +8 -2
- data/test/test_client_expire.rb +9 -1
- data/test/test_mt_accept.rb +3 -1
- data/test/test_server.rb +19 -6
- data/test/test_wbuf.rb +2 -2
- data/yahns.gemspec +1 -1
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b73379a257ad0e09cd00b6d1b1b316ca6913992
|
4
|
+
data.tar.gz: 1e5203cb1d70720bdab3f9624b9766e3d49a9d51
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c7a49cdbe694c1a27bd3f26d6db10b4b1f8ac11cf9307036957ba9df60aab266ef621cf515dcfd9eb592675648a0864b9949ba9b11ffccf083627a392353879
|
7
|
+
data.tar.gz: 2250ca7bf3fdfffbbb42cbb332cbe08bca48aa4c0e6066d3414e3248a2e666094ba2da07ff27312021558b67e45de59bdb10428fcd089c72bbfaeabd9f3488da
|
data/GIT-VERSION-GEN
CHANGED
data/INSTALL
CHANGED
@@ -6,3 +6,10 @@ No tarballs are currently provided.
|
|
6
6
|
|
7
7
|
You may also install yahns from the git source, see the HACKING document for
|
8
8
|
more details.
|
9
|
+
|
10
|
+
Debian GNU/kFreeBSD:
|
11
|
+
|
12
|
+
For now, you will need to define SENDFILE_BROKEN=1 in the env before
|
13
|
+
running yahns, and also install the "io-extra" RubyGem (tested on 1.2.7)
|
14
|
+
|
15
|
+
gem install -v 1.2.7 io-extra
|
data/README
CHANGED
@@ -44,11 +44,11 @@ Supported Platforms
|
|
44
44
|
|
45
45
|
yahns is developed primarily for modern GNU/Linux systems.
|
46
46
|
|
47
|
-
We
|
48
|
-
|
47
|
+
We have experimental support kqueue on FreeBSD (and possibly OpenBSD and
|
48
|
+
NetBSD). Non-Free systems/dependencies will never be supported.
|
49
49
|
|
50
50
|
Supported Ruby implementations:
|
51
|
-
* (Matz) Ruby 1.9.3 and later (we develop
|
51
|
+
* (Matz) Ruby 1.9.3 and later (we develop (and host our website) on trunk)
|
52
52
|
* Rubinius 2.0 or later (best-effort)
|
53
53
|
|
54
54
|
Contact
|
data/lib/yahns.rb
CHANGED
@@ -30,7 +30,7 @@ module Yahns # :nodoc:
|
|
30
30
|
#
|
31
31
|
# Yahns::START[0] = "/home/bofh/2.0.0/bin/yahns"
|
32
32
|
START = {
|
33
|
-
:argv => ARGV.map
|
33
|
+
:argv => ARGV.map(&:dup),
|
34
34
|
0 => $0.dup,
|
35
35
|
}
|
36
36
|
|
@@ -57,7 +57,7 @@ end
|
|
57
57
|
|
58
58
|
# FIXME: require lazily
|
59
59
|
require_relative 'yahns/log'
|
60
|
-
require_relative 'yahns/
|
60
|
+
require_relative 'yahns/queue'
|
61
61
|
require_relative 'yahns/stream_input'
|
62
62
|
require_relative 'yahns/tee_input'
|
63
63
|
require_relative 'yahns/queue_egg'
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# Copyright (C) 2014, Eric Wong <normalperson@yhbt.net> and all contributors
|
3
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
#
|
5
|
+
# This is the dangerous, low-level kqueue interface for sleepy_penguin
|
6
|
+
# It is safe as long as you're aware of all potential concurrency
|
7
|
+
# issues given multithreading, GC, and kqueue itself.
|
8
|
+
class Yahns::Queue < SleepyPenguin::Kqueue::IO # :nodoc:
|
9
|
+
include SleepyPenguin
|
10
|
+
attr_accessor :fdmap # Yahns::Fdmap
|
11
|
+
|
12
|
+
# public
|
13
|
+
QEV_QUIT = nil # Level Trigger for QueueQuitter
|
14
|
+
QEV_RD = EvFilt::READ
|
15
|
+
QEV_WR = EvFilt::WRITE
|
16
|
+
|
17
|
+
ADD_ONESHOT = Ev::ADD | Ev::ONESHOT # private
|
18
|
+
|
19
|
+
def self.new
|
20
|
+
rv = super
|
21
|
+
rv.close_on_exec = true
|
22
|
+
rv
|
23
|
+
end
|
24
|
+
|
25
|
+
# for HTTP and HTTPS servers, we rely on the io writing to us, first
|
26
|
+
# flags: QEV_RD/QEV_WR (usually QEV_RD)
|
27
|
+
def queue_add(io, flags)
|
28
|
+
# order is very important here, this thread cannot do anything with
|
29
|
+
# io once we've issued epoll_ctl() because another thread may use it
|
30
|
+
@fdmap.add(io)
|
31
|
+
fflags = ADD_ONESHOT
|
32
|
+
if flags == QEV_QUIT
|
33
|
+
fflags = Ev::ADD
|
34
|
+
flags = QEV_WR
|
35
|
+
end
|
36
|
+
kevent(Kevent[io.fileno, flags, fflags, 0, 0, io])
|
37
|
+
end
|
38
|
+
|
39
|
+
def thr_init
|
40
|
+
Thread.current[:yahns_rbuf] = ""
|
41
|
+
Thread.current[:yahns_fdmap] = @fdmap
|
42
|
+
end
|
43
|
+
|
44
|
+
def queue_del(io)
|
45
|
+
# do not bother with kevent EV_DELETE, it may be tricky to get right,
|
46
|
+
# we only did it in epoll since Eric knows the epoll internals well.
|
47
|
+
@fdmap.forget(io)
|
48
|
+
end
|
49
|
+
|
50
|
+
# returns an array of infinitely running threads
|
51
|
+
def worker_thread(logger, max_events)
|
52
|
+
Thread.new do
|
53
|
+
thr_init
|
54
|
+
begin
|
55
|
+
kevent(nil, max_events) do |_,_,_,_,_,io| # don't care for flags for now
|
56
|
+
# Note: we absolutely must not do anything with io after
|
57
|
+
# we've called epoll_ctl on it, io is exclusive to this
|
58
|
+
# thread only until epoll_ctl is called on it.
|
59
|
+
case rv = io.yahns_step
|
60
|
+
when :wait_readable
|
61
|
+
kevent(Kevent[io.fileno, QEV_RD, ADD_ONESHOT, 0, 0, io])
|
62
|
+
when :wait_writable
|
63
|
+
kevent(Kevent[io.fileno, QEV_WR, ADD_ONESHOT, 0, 0, io])
|
64
|
+
when :ignore # only used by rack.hijack
|
65
|
+
# we cannot EV_DELETE after hijacking, the hijacker
|
66
|
+
# may have already closed it Likewise, io.fileno is not
|
67
|
+
# expected to work, so we had to erase it from fdmap before hijack
|
68
|
+
when nil, :close
|
69
|
+
# this must be the ONLY place where we call IO#close on
|
70
|
+
# things that got inside the queue
|
71
|
+
@fdmap.sync_close(io)
|
72
|
+
else
|
73
|
+
raise "BUG: #{io.inspect}#yahns_step returned: #{rv.inspect}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
rescue => e
|
77
|
+
break if closed? # can still happen due to shutdown_timeout
|
78
|
+
Yahns::Log.exception(logger, 'queue loop', e)
|
79
|
+
end while true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -5,9 +5,8 @@
|
|
5
5
|
class Yahns::QueueQuitter # :nodoc:
|
6
6
|
attr_reader :to_io
|
7
7
|
def initialize
|
8
|
-
reader, @to_io = IO.pipe
|
8
|
+
@reader, @to_io = IO.pipe
|
9
9
|
@to_io.close_on_exec = true
|
10
|
-
reader.close
|
11
10
|
end
|
12
11
|
|
13
12
|
def yahns_step
|
@@ -19,6 +18,7 @@ class Yahns::QueueQuitter # :nodoc:
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def close
|
21
|
+
@reader.close
|
22
22
|
@to_io.close
|
23
23
|
end
|
24
24
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# Copyright (C) 2009-2014, Eric Wong <normalperson@yhbt.net> et. al.
|
3
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
require 'io/extra' # gem install io-extra
|
5
|
+
|
6
|
+
module Yahns::SendfileCompat
|
7
|
+
def trysendfile(io, offset, count)
|
8
|
+
return 0 if count == 0
|
9
|
+
count = 0x4000 if count > 0x4000
|
10
|
+
str = IO.pread(io.fileno, count, offset)
|
11
|
+
if count > str.bytesize
|
12
|
+
raise EOFError, "end of file reached"
|
13
|
+
end
|
14
|
+
n = 0
|
15
|
+
case rv = kgio_trywrite(str)
|
16
|
+
when String # partial write, keep trying
|
17
|
+
n += (str.bytesize - rv.bytesize)
|
18
|
+
str = rv
|
19
|
+
when :wait_writable, :wait_readable
|
20
|
+
return n > 0 ? n : rv
|
21
|
+
when nil
|
22
|
+
return n + str.bytesize # yay!
|
23
|
+
end while true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class IO
|
28
|
+
include Yahns::SendfileCompat
|
29
|
+
end
|
data/lib/yahns/sigevent_pipe.rb
CHANGED
data/lib/yahns/wbuf.rb
CHANGED
@@ -30,6 +30,14 @@ require_relative 'wbuf_common'
|
|
30
30
|
class Yahns::Wbuf # :nodoc:
|
31
31
|
include Yahns::WbufCommon
|
32
32
|
|
33
|
+
# TODO: Figure out why this hack is needed to pass output buffering tests.
|
34
|
+
# It could be a bug in our code, Ruby, the sendfile gem, or FreeBSD itself.
|
35
|
+
# Tested on FreeBSD fbsd 9.2-RELEASE FreeBSD 9.2-RELEASE #0 r255898
|
36
|
+
# We are able to use bypass mode on Linux to reduce buffering in some
|
37
|
+
# cases. Without bypass mode, we must always finish writing the entire
|
38
|
+
# response completely before sending more data to the client.
|
39
|
+
bypass_ok = RUBY_PLATFORM =~ /linux/
|
40
|
+
|
33
41
|
def initialize(body, persist, tmpdir)
|
34
42
|
@tmpio = Yahns::TmpIO.new(tmpdir)
|
35
43
|
@sf_offset = @sf_count = 0
|
@@ -67,7 +75,12 @@ class Yahns::Wbuf # :nodoc:
|
|
67
75
|
@tmpio.rewind
|
68
76
|
@bypass = true
|
69
77
|
nil
|
70
|
-
end
|
78
|
+
end if bypass_ok
|
79
|
+
|
80
|
+
def wbuf_write(client, buf)
|
81
|
+
@sf_count += @tmpio.write(buf)
|
82
|
+
:wait_writable
|
83
|
+
end unless bypass_ok
|
71
84
|
|
72
85
|
# called by last wbuf_flush
|
73
86
|
def wbuf_close(client)
|
data/lib/yahns/wbuf_common.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
# Copyright (C) 2009-2013, Eric Wong <normalperson@yhbt.net> et. al.
|
3
3
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
-
|
4
|
+
if ENV["SENDFILE_BROKEN"]
|
5
|
+
require_relative 'sendfile_compat'
|
6
|
+
else
|
7
|
+
require 'sendfile'
|
8
|
+
end
|
9
|
+
|
5
10
|
module Yahns::WbufCommon # :nodoc:
|
6
11
|
# returns nil on success, :wait_*able when blocked
|
7
12
|
# currently, we rely on each thread having exclusive access to the
|
@@ -25,7 +30,8 @@ module Yahns::WbufCommon # :nodoc:
|
|
25
30
|
raise "BUG: rv=#{rv.inspect} " \
|
26
31
|
"on tmpio=#{@tmpio.inspect} " \
|
27
32
|
"sf_offset=#@sf_offset sf_count=#@sf_count"
|
28
|
-
end while
|
33
|
+
end while @sf_count > 0
|
34
|
+
wbuf_close(client)
|
29
35
|
end
|
30
36
|
|
31
37
|
def wbuf_close_common(client)
|
data/test/helper.rb
CHANGED
@@ -36,6 +36,12 @@ if ENV["COVERAGE"]
|
|
36
36
|
# filter out stuff that's not in our project
|
37
37
|
COVMATCH =~ filename or next
|
38
38
|
|
39
|
+
# For compatibility with https://bugs.ruby-lang.org/issues/9508
|
40
|
+
# TODO: support those features if that gets merged into mainline
|
41
|
+
unless Array === counts
|
42
|
+
counts = counts[:lines]
|
43
|
+
end
|
44
|
+
|
39
45
|
merge = prev[filename] || []
|
40
46
|
merge = merge
|
41
47
|
counts.each_with_index do |count, i|
|
data/test/test_buffer_tmpdir.rb
CHANGED
@@ -9,12 +9,18 @@ class TestBufferTmpdir < Testcase
|
|
9
9
|
attr_reader :ino, :tmpdir
|
10
10
|
|
11
11
|
def setup
|
12
|
-
@ino =
|
12
|
+
@ino = nil
|
13
|
+
begin
|
14
|
+
@ino = SleepyPenguin::Inotify.new(:CLOEXEC)
|
15
|
+
rescue
|
16
|
+
skip "test needs inotify"
|
17
|
+
end
|
13
18
|
@tmpdir = Dir.mktmpdir
|
14
19
|
server_helper_setup
|
15
20
|
end
|
16
21
|
|
17
22
|
def teardown
|
23
|
+
return unless @ino
|
18
24
|
server_helper_teardown
|
19
25
|
@ino.close
|
20
26
|
FileUtils.rm_rf @tmpdir
|
@@ -100,4 +106,4 @@ class TestBufferTmpdir < Testcase
|
|
100
106
|
c.close if c
|
101
107
|
quit_wait(pid)
|
102
108
|
end
|
103
|
-
end
|
109
|
+
end
|
data/test/test_client_expire.rb
CHANGED
@@ -149,9 +149,17 @@ class TestClientExpire < Testcase
|
|
149
149
|
Process.waitpid2(_pid)
|
150
150
|
end
|
151
151
|
end
|
152
|
+
|
153
|
+
# this seems to be needed in Debian GNU/kFreeBSD
|
154
|
+
linux = !!(RUBY_PLATFORM =~ /linux/)
|
155
|
+
sleep(1) unless linux
|
156
|
+
|
152
157
|
[ f, s ].each do |io|
|
153
158
|
assert_raises(Errno::EPIPE,Errno::ECONNRESET) do
|
154
|
-
req.each_byte
|
159
|
+
req.each_byte do |b|
|
160
|
+
io.write(b.chr)
|
161
|
+
sleep(0.01) unless linux
|
162
|
+
end
|
155
163
|
end
|
156
164
|
io.close
|
157
165
|
end
|
data/test/test_mt_accept.rb
CHANGED
@@ -10,6 +10,8 @@ class TestMtAccept < Testcase
|
|
10
10
|
alias teardown server_helper_teardown
|
11
11
|
|
12
12
|
def test_mt_accept
|
13
|
+
skip "Linux kernel required" unless RUBY_PLATFORM =~ /linux/
|
14
|
+
skip "/proc not mounted" unless File.directory?("/proc")
|
13
15
|
err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
|
14
16
|
opts = { threads: 1 }
|
15
17
|
cfg.instance_eval do
|
@@ -45,4 +47,4 @@ class TestMtAccept < Testcase
|
|
45
47
|
ensure
|
46
48
|
quit_wait(pid)
|
47
49
|
end
|
48
|
-
end
|
50
|
+
end
|
data/test/test_server.rb
CHANGED
@@ -178,11 +178,14 @@ class TestServer < Testcase
|
|
178
178
|
end
|
179
179
|
|
180
180
|
def test_check_client_connection
|
181
|
+
tmpdir = Dir.mktmpdir
|
182
|
+
sock = "#{tmpdir}/sock"
|
183
|
+
unix_srv = UNIXServer.new(sock)
|
184
|
+
unix_srv.close_on_exec = true
|
181
185
|
msgs = %w(ZZ zz)
|
182
186
|
err = @err
|
183
187
|
cfg = Yahns::Config.new
|
184
188
|
bpipe = cloexec_pipe
|
185
|
-
host, port = @srv.addr[3], @srv.addr[1]
|
186
189
|
cfg.instance_eval do
|
187
190
|
ru = lambda { |e|
|
188
191
|
case e['PATH_INFO']
|
@@ -205,7 +208,7 @@ class TestServer < Testcase
|
|
205
208
|
}
|
206
209
|
GTL.synchronize {
|
207
210
|
app(:rack, ru) {
|
208
|
-
listen
|
211
|
+
listen sock
|
209
212
|
check_client_connection true
|
210
213
|
# needed to avoid concurrency with check_client_connection
|
211
214
|
queue { worker_threads 1 }
|
@@ -223,12 +226,13 @@ class TestServer < Testcase
|
|
223
226
|
|
224
227
|
pid = fork do
|
225
228
|
bpipe[1].close
|
226
|
-
ENV["YAHNS_FD"] =
|
229
|
+
ENV["YAHNS_FD"] = unix_srv.fileno.to_s
|
227
230
|
srv.start.join
|
228
231
|
end
|
229
232
|
bpipe[0].close
|
230
|
-
a =
|
231
|
-
b =
|
233
|
+
a = UNIXSocket.new(sock)
|
234
|
+
b = UNIXSocket.new(sock)
|
235
|
+
b.close_on_exec = a.close_on_exec = true
|
232
236
|
a.write("GET /sleep HTTP/1.0\r\n\r\n")
|
233
237
|
r = IO.select([a], nil, nil, 4)
|
234
238
|
assert r, "nothing ready"
|
@@ -250,10 +254,19 @@ class TestServer < Testcase
|
|
250
254
|
assert_equal msgs.join, buf.split(/\r\n\r\n/)[1]
|
251
255
|
|
252
256
|
# do things still work?
|
253
|
-
|
257
|
+
c = UNIXSocket.new(sock)
|
258
|
+
c.write "GET /\r\n\r\n"
|
259
|
+
assert_equal "HI", c.read
|
260
|
+
c.close
|
254
261
|
a.close
|
262
|
+
rescue => e
|
263
|
+
warn e.class
|
264
|
+
warn e.message
|
265
|
+
warn e.backtrace.join("\n")
|
255
266
|
ensure
|
267
|
+
unix_srv.close
|
256
268
|
quit_wait(pid)
|
269
|
+
FileUtils.rm_rf(tmpdir)
|
257
270
|
end
|
258
271
|
|
259
272
|
def test_mp
|
data/test/test_wbuf.rb
CHANGED
@@ -81,8 +81,8 @@ class TestWbuf < Testcase
|
|
81
81
|
assert_equal b, IO.select([b], nil, nil, 5)[0][0]
|
82
82
|
b.read(nr - 2) if nr > 2
|
83
83
|
assert_equal b, IO.select([b], nil, nil, 5)[0][0]
|
84
|
-
assert_equal "HI", b.read(2)
|
85
|
-
assert_equal
|
84
|
+
assert_equal "HI", b.read(2), "read the end of the response"
|
85
|
+
assert_equal true, wbuf.wbuf_flush(a)
|
86
86
|
ensure
|
87
87
|
a.close
|
88
88
|
b.close
|
data/yahns.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.files = manifest
|
13
13
|
s.add_dependency(%q<kgio>, '~> 2.9')
|
14
14
|
s.add_dependency(%q<sleepy_penguin>, '~> 3.2')
|
15
|
-
s.add_dependency(%q<sendfile>, '~> 1.2
|
15
|
+
s.add_dependency(%q<kgio-sendfile>, '~> 1.2')
|
16
16
|
s.add_dependency(%q<unicorn>, '~> 4.6', '>= 4.6.3')
|
17
17
|
|
18
18
|
# minitest is standard in Ruby 2.0, 4.3 is packaged with Ruby 2.0.0,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yahns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yahns hackers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kgio
|
@@ -39,19 +39,19 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: sendfile
|
42
|
+
name: kgio-sendfile
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.2
|
47
|
+
version: '1.2'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.2
|
54
|
+
version: '1.2'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: unicorn
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -152,10 +152,12 @@ files:
|
|
152
152
|
- lib/yahns/queue.rb
|
153
153
|
- lib/yahns/queue_egg.rb
|
154
154
|
- lib/yahns/queue_epoll.rb
|
155
|
+
- lib/yahns/queue_kqueue.rb
|
155
156
|
- lib/yahns/queue_quitter.rb
|
156
157
|
- lib/yahns/queue_quitter_pipe.rb
|
157
158
|
- lib/yahns/rack.rb
|
158
159
|
- lib/yahns/rackup_handler.rb
|
160
|
+
- lib/yahns/sendfile_compat.rb
|
159
161
|
- lib/yahns/server.rb
|
160
162
|
- lib/yahns/server_mp.rb
|
161
163
|
- lib/yahns/sigevent.rb
|
@@ -223,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
223
225
|
version: '0'
|
224
226
|
requirements: []
|
225
227
|
rubyforge_project:
|
226
|
-
rubygems_version: 2.2.
|
228
|
+
rubygems_version: 2.2.2
|
227
229
|
signing_key:
|
228
230
|
specification_version: 4
|
229
231
|
summary: sleepy, multi-threaded, non-blocking application server
|