yahns 0.0.1 → 0.0.2

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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Documentation/.gitignore +5 -0
  4. data/Documentation/GNUmakefile +50 -0
  5. data/Documentation/yahns-rackup.txt +152 -0
  6. data/Documentation/yahns.txt +68 -0
  7. data/Documentation/yahns_config.txt +563 -0
  8. data/GIT-VERSION-GEN +1 -1
  9. data/GNUmakefile +14 -7
  10. data/HACKING +56 -0
  11. data/INSTALL +8 -0
  12. data/README +15 -2
  13. data/Rakefile +2 -2
  14. data/bin/yahns +1 -2
  15. data/bin/yahns-rackup +9 -0
  16. data/examples/yahns_multi.conf.rb +14 -4
  17. data/examples/yahns_rack_basic.conf.rb +17 -1
  18. data/extras/README +16 -0
  19. data/extras/autoindex.rb +151 -0
  20. data/extras/exec_cgi.rb +108 -0
  21. data/extras/proxy_pass.rb +210 -0
  22. data/extras/try_gzip_static.rb +208 -0
  23. data/lib/yahns.rb +5 -2
  24. data/lib/yahns/acceptor.rb +64 -22
  25. data/lib/yahns/cap_input.rb +2 -2
  26. data/lib/yahns/{client_expire_portable.rb → client_expire_generic.rb} +12 -11
  27. data/lib/yahns/{client_expire.rb → client_expire_tcpi.rb} +7 -6
  28. data/lib/yahns/config.rb +107 -22
  29. data/lib/yahns/daemon.rb +2 -0
  30. data/lib/yahns/fdmap.rb +28 -9
  31. data/lib/yahns/http_client.rb +123 -37
  32. data/lib/yahns/http_context.rb +21 -3
  33. data/lib/yahns/http_response.rb +80 -19
  34. data/lib/yahns/log.rb +23 -4
  35. data/lib/yahns/queue_epoll.rb +20 -9
  36. data/lib/yahns/queue_quitter.rb +16 -0
  37. data/lib/yahns/queue_quitter_pipe.rb +24 -0
  38. data/lib/yahns/rack.rb +0 -1
  39. data/lib/yahns/rackup_handler.rb +57 -0
  40. data/lib/yahns/server.rb +189 -59
  41. data/lib/yahns/server_mp.rb +43 -35
  42. data/lib/yahns/sigevent_pipe.rb +1 -0
  43. data/lib/yahns/socket_helper.rb +37 -11
  44. data/lib/yahns/stream_file.rb +14 -4
  45. data/lib/yahns/stream_input.rb +13 -7
  46. data/lib/yahns/tcp_server.rb +7 -0
  47. data/lib/yahns/tmpio.rb +10 -3
  48. data/lib/yahns/unix_server.rb +7 -0
  49. data/lib/yahns/wbuf.rb +19 -2
  50. data/lib/yahns/wbuf_common.rb +10 -3
  51. data/lib/yahns/wbuf_str.rb +24 -0
  52. data/lib/yahns/worker.rb +5 -26
  53. data/test/helper.rb +15 -5
  54. data/test/server_helper.rb +37 -1
  55. data/test/test_bin.rb +17 -8
  56. data/test/test_buffer_tmpdir.rb +103 -0
  57. data/test/test_client_expire.rb +71 -35
  58. data/test/test_client_max_body_size.rb +5 -13
  59. data/test/test_config.rb +1 -1
  60. data/test/test_expect_100.rb +176 -0
  61. data/test/test_extras_autoindex.rb +53 -0
  62. data/test/test_extras_exec_cgi.rb +81 -0
  63. data/test/test_extras_exec_cgi.sh +35 -0
  64. data/test/test_extras_try_gzip_static.rb +177 -0
  65. data/test/test_input.rb +128 -0
  66. data/test/test_mt_accept.rb +48 -0
  67. data/test/test_output_buffering.rb +90 -63
  68. data/test/test_rack.rb +1 -1
  69. data/test/test_rack_hijack.rb +2 -6
  70. data/test/test_reopen_logs.rb +2 -8
  71. data/test/test_serve_static.rb +104 -8
  72. data/test/test_server.rb +448 -73
  73. data/test/test_stream_file.rb +1 -1
  74. data/test/test_unix_socket.rb +72 -0
  75. data/test/test_wbuf.rb +20 -17
  76. data/yahns.gemspec +3 -0
  77. metadata +57 -5
@@ -0,0 +1,24 @@
1
+ # -*- encoding: binary -*-
2
+ # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> et. al.
3
+ # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
4
+ require_relative 'wbuf_common'
5
+
6
+ class Yahns::WbufStr # :nodoc:
7
+ include Yahns::WbufCommon
8
+
9
+ def initialize(str, next_state)
10
+ @str = str
11
+ @next = next_state # :check_client_connection, :http_100_response
12
+ end
13
+
14
+ def wbuf_flush(client)
15
+ case rv = client.kgio_trywrite(@str)
16
+ when String
17
+ @str = rv
18
+ when :wait_writable, :wait_readable
19
+ return rv
20
+ when nil
21
+ return @next
22
+ end while true
23
+ end
24
+ end
data/lib/yahns/worker.rb CHANGED
@@ -23,36 +23,15 @@ class Yahns::Worker # :nodoc:
23
23
  # This causes the worker to gracefully exit if the master
24
24
  # dies unexpectedly.
25
25
  def yahns_step
26
- @to_io.kgio_tryread(11) == nil and Process.kill(:QUIT, $$)
27
- :wait_readable
26
+ if @to_io.kgio_tryread(11) == nil
27
+ Process.kill(:QUIT, $$)
28
+ @to_io.close
29
+ end
30
+ :ignore
28
31
  end
29
32
 
30
33
  # worker objects may be compared to just plain Integers
31
34
  def ==(other_nr) # :nodoc:
32
35
  @nr == other_nr
33
36
  end
34
-
35
- # Changes the worker process to the specified +user+ and +group+
36
- # This is only intended to be called from within the worker
37
- # process from the +after_fork+ hook. This should be called in
38
- # the +after_fork+ hook after any privileged functions need to be
39
- # run (e.g. to set per-worker CPU affinity, niceness, etc)
40
- #
41
- # Any and all errors raised within this method will be propagated
42
- # directly back to the caller (usually the +after_fork+ hook.
43
- # These errors commonly include ArgumentError for specifying an
44
- # invalid user/group and Errno::EPERM for insufficient privileges
45
- def user(user, group = nil)
46
- # we do not protect the caller, checking Process.euid == 0 is
47
- # insufficient because modern systems have fine-grained
48
- # capabilities. Let the caller handle any and all errors.
49
- uid = Etc.getpwnam(user).uid
50
- gid = Etc.getgrnam(group).gid if group
51
- Yahns::Log.chown_all(uid, gid)
52
- if gid && Process.egid != gid
53
- Process.initgroups(user, gid)
54
- Process::GID.change_privilege(gid)
55
- end
56
- Process.euid != uid and Process::UID.change_privilege(uid)
57
- end
58
37
  end
data/test/helper.rb CHANGED
@@ -3,6 +3,11 @@
3
3
  $stdout.sync = $stderr.sync = Thread.abort_on_exception = true
4
4
  $-w = true if RUBY_VERSION.to_f >= 2.0
5
5
  require 'thread'
6
+ require 'fileutils'
7
+
8
+ def rubyv
9
+ puts RUBY_DESCRIPTION
10
+ end
6
11
 
7
12
  # Global Test Lock, to protect:
8
13
  # Process.wait*, Dir.chdir, ENV, trap, require, etc...
@@ -11,13 +16,14 @@ GTL = Mutex.new
11
16
  # fork-aware coverage data gatherer, see also test/covshow.rb
12
17
  if ENV["COVERAGE"]
13
18
  require "coverage"
14
- COVMATCH = %r{/lib/yahns\b.*rb\z}
19
+ COVMATCH = %r{(/lib/yahns\b|extras/).*rb\z}
20
+ COVDUMPFILE = File.expand_path("coverage.dump")
15
21
 
16
22
  def __covmerge
17
23
  res = Coverage.result
18
24
 
19
- # do not create the file, Makefile does htis before any tests run
20
- File.open("coverage.dump", IO::RDWR) do |covtmp|
25
+ # do not create the file, Makefile does this before any tests run
26
+ File.open(COVDUMPFILE, IO::RDWR) do |covtmp|
21
27
  covtmp.binmode
22
28
  covtmp.sync = true
23
29
 
@@ -69,20 +75,20 @@ at_exit do
69
75
  # skipping @@after_run stuff in minitest since we don't need it
70
76
  case $!
71
77
  when nil, SystemExit
72
- mtobj.run(ARGV) if $$ == TSTART_PID
78
+ exit(mtobj.run(ARGV)) if $$ == TSTART_PID
73
79
  end
74
80
  end
75
81
 
76
82
  require "tempfile"
77
83
  require 'tmpdir'
78
84
  class Dir
79
- require 'fileutils'
80
85
  def Dir.mktmpdir
81
86
  begin
82
87
  d = "#{Dir.tmpdir}/#$$.#{rand}"
83
88
  Dir.mkdir(d)
84
89
  rescue Errno::EEXIST
85
90
  end while true
91
+ return d unless block_given?
86
92
  begin
87
93
  yield d
88
94
  ensure
@@ -109,6 +115,10 @@ class IO
109
115
  end
110
116
  end if ! IO.method_defined?(:nread) && RUBY_PLATFORM =~ /linux/
111
117
 
118
+ def cloexec_pipe
119
+ IO.pipe.each { |io| io.close_on_exec = true }
120
+ end
121
+
112
122
  require 'yahns'
113
123
 
114
124
  # needed for parallel (MT) tests)
@@ -29,10 +29,16 @@ module ServerHelper
29
29
 
30
30
  def quit_wait(pid)
31
31
  pid or return
32
+ err = $!
32
33
  Process.kill(:QUIT, pid)
33
34
  _, status = Timeout.timeout(10) { Process.waitpid2(pid) }
34
35
  assert status.success?, status.inspect
35
- rescue Timeout::Error
36
+ rescue Timeout::Error => tout
37
+ err ||= tout
38
+ begin
39
+ warn "#{err.message} (#{err.class})"
40
+ err.backtrace.each { |l| warn l }
41
+ end
36
42
  if RUBY_PLATFORM =~ /linux/
37
43
  system("lsof -p #{pid}")
38
44
  warn "#{pid} failed to die, waiting for user to inspect"
@@ -45,6 +51,7 @@ module ServerHelper
45
51
  def get_tcp_client(host, port, tries = 500)
46
52
  begin
47
53
  c = TCPSocket.new(host, port)
54
+ c.close_on_exec = true
48
55
  return c
49
56
  rescue Errno::ECONNREFUSED
50
57
  raise if tries < 0
@@ -63,4 +70,33 @@ module ServerHelper
63
70
  @err = tmpfile(%w(srv .err))
64
71
  @ru = nil
65
72
  end
73
+
74
+ def mkserver(cfg)
75
+ fork do
76
+ ENV["YAHNS_FD"] = @srv.fileno.to_s
77
+ yield if block_given?
78
+ Yahns::Server.new(cfg).start.join
79
+ end
80
+ end
81
+
82
+ def wait_for_full(c)
83
+ prev = 0
84
+ prev_time = Time.now
85
+ begin
86
+ nr = c.nread
87
+ break if nr > 0 && nr == prev && (Time.now - prev_time) > 0.5
88
+ if nr != prev
89
+ prev = nr
90
+ prev_time = Time.now
91
+ end
92
+ Thread.pass
93
+ end while sleep(0.1)
94
+ end
95
+ end
96
+
97
+ module TrywriteBlocked
98
+ def kgio_trywrite(*args)
99
+ return :wait_writable if $_tw_block_on.include?($_tw_blocked += 1)
100
+ super
101
+ end
66
102
  end
data/test/test_bin.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
3
3
  require_relative 'server_helper'
4
4
  class TestBin < Testcase
5
- parallelize_me!
5
+ ENV["N"].to_i > 1 and parallelize_me!
6
6
  include ServerHelper
7
7
  alias teardown server_helper_teardown
8
8
 
@@ -40,20 +40,32 @@ class TestBin < Testcase
40
40
  cfg.puts " listen ENV['YAHNS_TEST_LISTEN']"
41
41
  cfg.puts "end"
42
42
  @cmd.concat(%W(-D -c #{cfg.path}))
43
- addr = IO.pipe
43
+ addr = cloexec_pipe
44
44
  pid = fork do
45
+ opts = { close_others: true }
46
+ addr[0].close
45
47
  if inherit
46
- @cmd << { @srv.fileno => @srv }
48
+ opts[@srv.fileno] = @srv
47
49
  ENV["YAHNS_FD"] = @srv.fileno.to_s
48
50
  else
51
+ # we must create the socket inside the child and tell the parent
52
+ # about it to avoid sharing
49
53
  @srv = TCPServer.new(ENV["TEST_HOST"] || "127.0.0.1", 0)
50
- @srv.close_on_exec = true # needed for 1.9.3
51
54
  end
55
+ @cmd << opts
52
56
  host, port = @srv.addr[3], @srv.addr[1]
53
57
  listen = ENV["YAHNS_TEST_LISTEN"] = "#{host}:#{port}"
54
58
  addr[1].write(listen)
55
59
  addr[1].close
56
- addr[0].close
60
+
61
+ # close/FD_CLOEXEC may be insufficient since the socket could be
62
+ # released asynchronously, leading to occasional test failures.
63
+ # Even with a synchronous FD_CLOEXEC, there's a chance of a race
64
+ # because the server does not bind right away.
65
+ unless inherit
66
+ @srv.shutdown
67
+ @srv.close
68
+ end
57
69
  exec(*@cmd)
58
70
  end
59
71
  addr[1].close
@@ -177,9 +189,6 @@ class TestBin < Testcase
177
189
  else
178
190
  poke_until_dead newpid
179
191
  end
180
- rescue => e
181
- Yahns::Log.exception(Logger.new($stderr), "test", e)
182
- raise
183
192
  ensure
184
193
  File.unlink(exe) if exe
185
194
  cfg.close! if cfg
@@ -0,0 +1,103 @@
1
+ # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
2
+ # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
3
+ require_relative 'server_helper'
4
+ require 'sleepy_penguin'
5
+
6
+ class TestBufferTmpdir < Testcase
7
+ ENV["N"].to_i > 1 and parallelize_me!
8
+ include ServerHelper
9
+ attr_reader :ino, :tmpdir
10
+
11
+ def setup
12
+ @ino = SleepyPenguin::Inotify.new(:CLOEXEC)
13
+ @tmpdir = Dir.mktmpdir
14
+ server_helper_setup
15
+ end
16
+
17
+ def teardown
18
+ server_helper_teardown
19
+ @ino.close
20
+ FileUtils.rm_rf @tmpdir
21
+ end
22
+
23
+ class GiantBody
24
+ # just spew until the client gives up
25
+ def each
26
+ nr = 16384
27
+ buf = "#{nr.to_s(16)}\r\n#{("!" * nr)}\r\n"
28
+ loop do
29
+ yield buf
30
+ end
31
+ end
32
+ end
33
+
34
+ def test_output_buffer_tmpdir
35
+ opts = { tmpdir: @tmpdir }
36
+ err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
37
+ pid = mkserver(cfg) do
38
+ cfg.instance_eval do
39
+ ru = lambda { |e|
40
+ h = {
41
+ "Transfer-Encoding" => "chunked",
42
+ "Content-Type" => "text/plain"
43
+ }
44
+ [ 200, h, GiantBody.new ]
45
+ }
46
+ app(:rack, ru) do
47
+ listen "#{host}:#{port}"
48
+ output_buffering true, opts
49
+ end
50
+ stderr_path err.path
51
+ end
52
+ end
53
+ @ino.add_watch @tmpdir, [:CREATE, :DELETE]
54
+ c = get_tcp_client(host, port)
55
+ c.write "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
56
+ Timeout.timeout(30) do
57
+ event = @ino.take
58
+ assert_equal [:CREATE], event.events
59
+ name = event.name
60
+ event = @ino.take
61
+ assert_equal [:DELETE], event.events
62
+ assert_equal name, event.name
63
+ refute File.exist?("#@tmpdir/#{name}")
64
+ end
65
+ ensure
66
+ c.close if c
67
+ quit_wait(pid)
68
+ end
69
+
70
+ def test_input_buffer_lazy; input_buffer(:lazy); end
71
+ def test_input_buffer_true; input_buffer(true); end
72
+
73
+ def input_buffer(btype)
74
+ opts = { tmpdir: @tmpdir }
75
+ err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
76
+ pid = mkserver(cfg) do
77
+ cfg.instance_eval do
78
+ require 'rack/lobster'
79
+ app(:rack, Rack::Lobster.new) do
80
+ listen "#{host}:#{port}"
81
+ input_buffering btype, opts
82
+ end
83
+ stderr_path err.path
84
+ end
85
+ end
86
+ @ino.add_watch tmpdir, [:CREATE, :DELETE]
87
+ c = get_tcp_client(host, port)
88
+ nr = 16384 # must be > client_body_buffer_size
89
+ c.write "POST / HTTP/1.0\r\nContent-Length: #{nr}\r\n\r\n"
90
+ Timeout.timeout(30) do
91
+ event = ino.take
92
+ assert_equal [:CREATE], event.events
93
+ name = event.name
94
+ event = ino.take
95
+ assert_equal [:DELETE], event.events
96
+ assert_equal name, event.name
97
+ refute File.exist?("#{tmpdir}/#{name}")
98
+ end
99
+ ensure
100
+ c.close if c
101
+ quit_wait(pid)
102
+ end
103
+ end if SleepyPenguin.const_defined?(:Inotify)
@@ -3,7 +3,7 @@
3
3
  require_relative 'server_helper'
4
4
 
5
5
  class TestClientExpire < Testcase
6
- parallelize_me!
6
+ ENV["N"].to_i > 1 and parallelize_me!
7
7
  include ServerHelper
8
8
  alias setup server_helper_setup
9
9
  alias teardown server_helper_teardown
@@ -22,11 +22,7 @@ class TestClientExpire < Testcase
22
22
  end
23
23
  logger(Logger.new(err.path))
24
24
  end
25
- srv = Yahns::Server.new(cfg)
26
- pid = fork do
27
- ENV["YAHNS_FD"] = @srv.fileno.to_s
28
- srv.start.join
29
- end
25
+ pid = mkserver(cfg)
30
26
  Net::HTTP.start(host, port) { |h|
31
27
  res = h.get("/")
32
28
  assert_empty res.body
@@ -51,16 +47,13 @@ class TestClientExpire < Testcase
51
47
  end
52
48
  logger(Logger.new(err.path))
53
49
  end
54
- srv = Yahns::Server.new(cfg)
55
- pid = fork do
56
- ENV["YAHNS_FD"] = @srv.fileno.to_s
57
- srv.start.join
58
- end
59
- f = TCPSocket.new(host, port)
60
- s = TCPSocket.new(host, port)
50
+ pid = mkserver(cfg)
51
+ f = get_tcp_client(host, port)
52
+ s = get_tcp_client(host, port)
61
53
  req = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
62
54
  s.write(req)
63
- str = Timeout.timeout(20) { s.readpartial(666) }
55
+ str = ""
56
+ Timeout.timeout(20) { str << s.readpartial(666) until str =~ /\r\n\r\n/ }
64
57
  assert_match(%r{keep-alive}, str)
65
58
  sleep 2
66
59
  abe = tmpfile(%w(abe .err))
@@ -75,57 +68,100 @@ class TestClientExpire < Testcase
75
68
  end
76
69
  io.close
77
70
  end
78
- rescue => e
79
- Yahns::Log.exception(Logger.new($stderr), "test", e)
80
- raise
81
71
  ensure
82
72
  quit_wait(pid)
83
73
  end
84
74
 
75
+ # test EMFILE handling
85
76
  def test_client_expire_desperate
86
- skip "disabled since FD counts vary heavily in an MT process"
87
77
  err = @err
88
78
  cfg = Yahns::Config.new
89
79
  host, port = @srv.addr[3], @srv.addr[1]
90
80
  cfg.instance_eval do
91
81
  GTL.synchronize do
92
82
  h = { "Content-Length" => "0" }
93
- app(:rack, lambda { |e| [ 200, h, [] ]}) do
83
+ queue { worker_threads 1 }
84
+ ru = lambda { |e|
85
+ sleep(0.01) unless e["PATH_INFO"] == "/_"
86
+ [ 200, h, [] ]
87
+ }
88
+ app(:rack, ru) do
94
89
  listen "#{host}:#{port}", sndbuf: 2048, rcvbuf: 2048
95
- client_timeout 1
90
+ client_timeout 1.0
91
+ # FIXME: wbuf creation does not recover from EMFILE/ENFILE
92
+ output_buffering false
93
+ check_client_connection true
96
94
  end
97
95
  client_expire_threshold 1.0
98
96
  end
99
- logger(Logger.new(err.path))
97
+ stderr_path err.path
100
98
  end
101
- srv = Yahns::Server.new(cfg)
102
- pid = fork do
103
- Process.setrlimit :NOFILE, 512, 1024
104
- ENV["YAHNS_FD"] = @srv.fileno.to_s
105
- srv.start.join
99
+ pid = mkserver(cfg) do
100
+ keep = { $stderr => true, $stdout => true, $stdin => true, @srv => true }
101
+ ObjectSpace.each_object(IO) do |obj|
102
+ next if keep[obj]
103
+ begin
104
+ obj.close unless obj.closed?
105
+ rescue IOError # could be uninitialized
106
+ end
107
+ end
106
108
  end
107
- f = TCPSocket.new(host, port)
108
- s = TCPSocket.new(host, port)
109
+ f = get_tcp_client(host, port)
110
+ f.write "G"
111
+ s = get_tcp_client(host, port)
109
112
  req = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
110
113
  s.write(req)
111
- str = Timeout.timeout(20) { s.readpartial(666) }
114
+ str = ""
115
+ Timeout.timeout(20) { str << s.readpartial(666) until str =~ /\r\n\r\n/ }
112
116
  assert_match(%r{keep-alive}, str)
113
- sleep 3
114
- system "ab -c 1000 -n 10000 -k http://#{host}:#{port}/ 2>&1"
117
+ sleep 1
115
118
 
119
+ # ignore errors, just beat the crap out of the process
120
+ nr = Process.getrlimit(:NOFILE)[0] # 1024 is common
121
+ assert_operator nr, :>, 666, "increase RLIM_NOFILE (ulimit -n)"
122
+ nr -= 50
123
+ opts = { out: "/dev/null", err: "/dev/null", close_others: true }
124
+ begin
125
+ pids = 2.times.map do
126
+ fork do
127
+ exec(*%W(ab -c #{nr} -n 9999999 -v1 -k http://#{host}:#{port}/), opts)
128
+ end
129
+ end
130
+
131
+ re1 = %r{consider raising open file limits}
132
+ re2 = %r{dropping (\d+) of \d+ clients for timeout=\d+}
133
+ Timeout.timeout(30) do
134
+ n = 0
135
+ begin
136
+ buf = File.read(err.path)
137
+ if buf =~ re1 && buf =~ re2
138
+ n += $1.to_i
139
+ break if n >= 2
140
+ end
141
+ end while sleep(0.01)
142
+ end
143
+ ensure
144
+ # don't care for ab errors, they're likely
145
+ pids.each do |_pid|
146
+ Process.kill(:KILL, _pid)
147
+ Process.waitpid2(_pid)
148
+ end
149
+ end
116
150
  [ f, s ].each do |io|
117
151
  assert_raises(Errno::EPIPE,Errno::ECONNRESET) do
118
152
  req.each_byte { |b| io.write(b.chr) }
119
153
  end
120
154
  io.close
121
155
  end
156
+
157
+ # make sure the server still works
158
+ res = Net::HTTP.start(host, port) { |h| h.get("/_") }
159
+ assert_equal 200, res.code.to_i
160
+
122
161
  errs = File.readlines(err.path).grep(/ERROR/)
123
162
  File.truncate(err.path, 0) # avoid error on teardown
124
- re = %r{consider raising open file limits} # - accept, consider raising open file limits}
163
+ re = %r{consider raising open file limits}
125
164
  assert_equal errs.grep(re), errs
126
- rescue => e
127
- Yahns::Log.exception(Logger.new($stderr), "test", e)
128
- raise
129
165
  ensure
130
166
  quit_wait(pid)
131
167
  end