unicorn 4.9.0 → 6.0.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 +5 -5
- data/.gitattributes +5 -0
- data/.olddoc.yml +13 -6
- data/Application_Timeouts +7 -7
- data/DESIGN +2 -4
- data/Documentation/.gitignore +1 -3
- data/Documentation/unicorn.1 +222 -0
- data/Documentation/unicorn_rails.1 +207 -0
- data/FAQ +17 -8
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +121 -56
- data/HACKING +1 -2
- data/ISSUES +40 -41
- data/KNOWN_ISSUES +11 -11
- data/LICENSE +2 -2
- data/Links +24 -25
- data/PHILOSOPHY +0 -6
- data/README +46 -39
- data/SIGNALS +2 -2
- data/Sandbox +10 -9
- data/TODO +0 -2
- data/TUNING +30 -9
- data/archive/slrnpull.conf +1 -1
- data/bin/unicorn +4 -2
- data/bin/unicorn_rails +3 -3
- data/examples/big_app_gc.rb +1 -1
- data/examples/init.sh +36 -8
- data/examples/logrotate.conf +17 -2
- data/examples/nginx.conf +14 -14
- data/examples/unicorn.conf.minimal.rb +2 -2
- data/examples/unicorn.conf.rb +3 -6
- data/examples/unicorn.socket +11 -0
- data/examples/unicorn@.service +40 -0
- data/ext/unicorn_http/common_field_optimization.h +23 -5
- data/ext/unicorn_http/ext_help.h +0 -20
- data/ext/unicorn_http/extconf.rb +37 -1
- data/ext/unicorn_http/global_variables.h +1 -1
- data/ext/unicorn_http/httpdate.c +2 -2
- data/ext/unicorn_http/unicorn_http.rl +167 -170
- data/ext/unicorn_http/unicorn_http_common.rl +1 -1
- data/lib/unicorn.rb +66 -46
- data/lib/unicorn/configurator.rb +110 -44
- data/lib/unicorn/const.rb +2 -25
- data/lib/unicorn/http_request.rb +110 -31
- data/lib/unicorn/http_response.rb +17 -31
- data/lib/unicorn/http_server.rb +238 -157
- data/lib/unicorn/launcher.rb +1 -1
- data/lib/unicorn/oob_gc.rb +6 -6
- data/lib/unicorn/socket_helper.rb +58 -78
- data/lib/unicorn/stream_input.rb +8 -7
- data/lib/unicorn/tee_input.rb +8 -10
- data/lib/unicorn/tmpio.rb +8 -7
- data/lib/unicorn/util.rb +5 -4
- data/lib/unicorn/worker.rb +36 -23
- data/t/GNUmakefile +3 -72
- data/t/README +4 -4
- data/t/t0011-active-unix-socket.sh +1 -1
- data/t/t0012-reload-empty-config.sh +2 -1
- data/t/t0301-no-default-middleware-ignored-in-config.sh +25 -0
- data/t/t0301.ru +13 -0
- data/t/test-lib.sh +2 -2
- data/test/benchmark/README +14 -4
- data/test/benchmark/ddstream.ru +50 -0
- data/test/benchmark/readinput.ru +40 -0
- data/test/benchmark/uconnect.perl +66 -0
- data/test/exec/test_exec.rb +73 -19
- data/test/test_helper.rb +40 -31
- data/test/unit/test_ccc.rb +91 -0
- data/test/unit/test_droplet.rb +1 -1
- data/test/unit/test_http_parser.rb +46 -16
- data/test/unit/test_http_parser_ng.rb +97 -114
- data/test/unit/test_request.rb +10 -10
- data/test/unit/test_response.rb +28 -16
- data/test/unit/test_server.rb +86 -12
- data/test/unit/test_signals.rb +8 -8
- data/test/unit/test_socket_helper.rb +14 -10
- data/test/unit/test_upload.rb +9 -14
- data/test/unit/test_util.rb +27 -2
- data/unicorn.gemspec +27 -19
- metadata +24 -45
- data/Documentation/GNUmakefile +0 -30
- data/Documentation/unicorn.1.txt +0 -185
- data/Documentation/unicorn_rails.1.txt +0 -175
- data/examples/git.ru +0 -13
- data/lib/unicorn/app/exec_cgi.rb +0 -154
- data/lib/unicorn/app/inetd.rb +0 -109
- data/lib/unicorn/ssl_client.rb +0 -11
- data/lib/unicorn/ssl_configurator.rb +0 -104
- data/lib/unicorn/ssl_server.rb +0 -42
- data/t/hijack.ru +0 -42
- data/t/t0016-trust-x-forwarded-false.sh +0 -30
- data/t/t0017-trust-x-forwarded-true.sh +0 -30
- data/t/t0200-rack-hijack.sh +0 -27
- data/test/unit/test_http_parser_xftrust.rb +0 -38
- data/test/unit/test_sni_hostnames.rb +0 -47
data/test/unit/test_request.rb
CHANGED
@@ -34,7 +34,7 @@ def test_options
|
|
34
34
|
assert_equal '', env['REQUEST_PATH']
|
35
35
|
assert_equal '', env['PATH_INFO']
|
36
36
|
assert_equal '*', env['REQUEST_URI']
|
37
|
-
|
37
|
+
assert_kind_of Array, @lint.call(env)
|
38
38
|
end
|
39
39
|
|
40
40
|
def test_absolute_uri_with_query
|
@@ -44,7 +44,7 @@ def test_absolute_uri_with_query
|
|
44
44
|
assert_equal '/x', env['REQUEST_PATH']
|
45
45
|
assert_equal '/x', env['PATH_INFO']
|
46
46
|
assert_equal 'y=z', env['QUERY_STRING']
|
47
|
-
|
47
|
+
assert_kind_of Array, @lint.call(env)
|
48
48
|
end
|
49
49
|
|
50
50
|
def test_absolute_uri_with_fragment
|
@@ -55,7 +55,7 @@ def test_absolute_uri_with_fragment
|
|
55
55
|
assert_equal '/x', env['PATH_INFO']
|
56
56
|
assert_equal '', env['QUERY_STRING']
|
57
57
|
assert_equal 'frag', env['FRAGMENT']
|
58
|
-
|
58
|
+
assert_kind_of Array, @lint.call(env)
|
59
59
|
end
|
60
60
|
|
61
61
|
def test_absolute_uri_with_query_and_fragment
|
@@ -66,7 +66,7 @@ def test_absolute_uri_with_query_and_fragment
|
|
66
66
|
assert_equal '/x', env['PATH_INFO']
|
67
67
|
assert_equal 'a=b', env['QUERY_STRING']
|
68
68
|
assert_equal 'frag', env['FRAGMENT']
|
69
|
-
|
69
|
+
assert_kind_of Array, @lint.call(env)
|
70
70
|
end
|
71
71
|
|
72
72
|
def test_absolute_uri_unsupported_schemes
|
@@ -83,7 +83,7 @@ def test_x_forwarded_proto_https
|
|
83
83
|
"Host: foo\r\n\r\n")
|
84
84
|
env = @request.read(client)
|
85
85
|
assert_equal "https", env['rack.url_scheme']
|
86
|
-
|
86
|
+
assert_kind_of Array, @lint.call(env)
|
87
87
|
end
|
88
88
|
|
89
89
|
def test_x_forwarded_proto_http
|
@@ -92,7 +92,7 @@ def test_x_forwarded_proto_http
|
|
92
92
|
"Host: foo\r\n\r\n")
|
93
93
|
env = @request.read(client)
|
94
94
|
assert_equal "http", env['rack.url_scheme']
|
95
|
-
|
95
|
+
assert_kind_of Array, @lint.call(env)
|
96
96
|
end
|
97
97
|
|
98
98
|
def test_x_forwarded_proto_invalid
|
@@ -101,7 +101,7 @@ def test_x_forwarded_proto_invalid
|
|
101
101
|
"Host: foo\r\n\r\n")
|
102
102
|
env = @request.read(client)
|
103
103
|
assert_equal "http", env['rack.url_scheme']
|
104
|
-
|
104
|
+
assert_kind_of Array, @lint.call(env)
|
105
105
|
end
|
106
106
|
|
107
107
|
def test_rack_lint_get
|
@@ -109,7 +109,7 @@ def test_rack_lint_get
|
|
109
109
|
env = @request.read(client)
|
110
110
|
assert_equal "http", env['rack.url_scheme']
|
111
111
|
assert_equal '127.0.0.1', env['REMOTE_ADDR']
|
112
|
-
|
112
|
+
assert_kind_of Array, @lint.call(env)
|
113
113
|
end
|
114
114
|
|
115
115
|
def test_no_content_stringio
|
@@ -143,7 +143,7 @@ def test_rack_lint_put
|
|
143
143
|
"abcde")
|
144
144
|
env = @request.read(client)
|
145
145
|
assert ! env.include?(:http_body)
|
146
|
-
|
146
|
+
assert_kind_of Array, @lint.call(env)
|
147
147
|
end
|
148
148
|
|
149
149
|
def test_rack_lint_big_put
|
@@ -177,6 +177,6 @@ def client.kgio_read!(*args)
|
|
177
177
|
}
|
178
178
|
assert_nil env['rack.input'].read(bs)
|
179
179
|
env['rack.input'].rewind
|
180
|
-
|
180
|
+
assert_kind_of Array, @lint.call(env)
|
181
181
|
end
|
182
182
|
end
|
data/test/unit/test_response.rb
CHANGED
@@ -33,12 +33,20 @@ def test_response_headers
|
|
33
33
|
assert out.length > 0, "output didn't have data"
|
34
34
|
end
|
35
35
|
|
36
|
+
# ref: <CAO47=rJa=zRcLn_Xm4v2cHPr6c0UswaFC_omYFEH+baSxHOWKQ@mail.gmail.com>
|
37
|
+
def test_response_header_broken_nil
|
38
|
+
out = StringIO.new
|
39
|
+
http_response_write(out, 200, {"Nil" => nil}, %w(hysterical raisin))
|
40
|
+
assert ! out.closed?
|
41
|
+
|
42
|
+
assert_match %r{^Nil: \r\n}sm, out.string, 'nil accepted'
|
43
|
+
end
|
44
|
+
|
36
45
|
def test_response_string_status
|
37
46
|
out = StringIO.new
|
38
47
|
http_response_write(out,'200', {}, [])
|
39
48
|
assert ! out.closed?
|
40
49
|
assert out.length > 0, "output didn't have data"
|
41
|
-
assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/).size
|
42
50
|
end
|
43
51
|
|
44
52
|
def test_response_200
|
@@ -71,18 +79,6 @@ def test_status_header_added
|
|
71
79
|
out = StringIO.new
|
72
80
|
http_response_write(out,200, {"X-Whatever" => "stuff"}, [])
|
73
81
|
assert ! out.closed?
|
74
|
-
assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/i).size
|
75
|
-
end
|
76
|
-
|
77
|
-
def test_body_closed
|
78
|
-
expect_body = %w(1 2 3 4).join("\n")
|
79
|
-
body = StringIO.new(expect_body)
|
80
|
-
body.rewind
|
81
|
-
out = StringIO.new
|
82
|
-
http_response_write(out,200, {}, body)
|
83
|
-
assert ! out.closed?
|
84
|
-
assert body.closed?
|
85
|
-
assert_match(expect_body, out.string.split(/\r\n/).last)
|
86
82
|
end
|
87
83
|
|
88
84
|
def test_unknown_status_pass_through
|
@@ -91,9 +87,25 @@ def test_unknown_status_pass_through
|
|
91
87
|
assert ! out.closed?
|
92
88
|
headers = out.string.split(/\r\n\r\n/).first.split(/\r\n/)
|
93
89
|
assert %r{\AHTTP/\d\.\d 666 I AM THE BEAST\z}.match(headers[0])
|
94
|
-
status = headers.grep(/\AStatus:/i).first
|
95
|
-
assert status
|
96
|
-
assert_equal "Status: 666 I AM THE BEAST", status
|
97
90
|
end
|
98
91
|
|
92
|
+
def test_modified_rack_http_status_codes_late
|
93
|
+
r, w = IO.pipe
|
94
|
+
pid = fork do
|
95
|
+
r.close
|
96
|
+
# Users may want to globally override the status text associated
|
97
|
+
# with an HTTP status code in their app.
|
98
|
+
Rack::Utils::HTTP_STATUS_CODES[200] = "HI"
|
99
|
+
http_response_write(w, 200, {}, [])
|
100
|
+
w.close
|
101
|
+
end
|
102
|
+
w.close
|
103
|
+
assert_equal "HTTP/1.1 200 HI\r\n", r.gets
|
104
|
+
r.read # just drain the pipe
|
105
|
+
pid, status = Process.waitpid2(pid)
|
106
|
+
assert status.success?, status.inspect
|
107
|
+
ensure
|
108
|
+
r.close
|
109
|
+
w.close unless w.closed?
|
110
|
+
end
|
99
111
|
end
|
data/test/unit/test_server.rb
CHANGED
@@ -17,12 +17,40 @@ def call(env)
|
|
17
17
|
while env['rack.input'].read(4096)
|
18
18
|
end
|
19
19
|
[200, { 'Content-Type' => 'text/plain' }, ['hello!\n']]
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
rescue Unicorn::ClientShutdown, Unicorn::HttpParserError => e
|
21
|
+
$stderr.syswrite("#{e.class}: #{e.message} #{e.backtrace.empty?}\n")
|
22
|
+
raise e
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
class TestEarlyHintsHandler
|
27
|
+
def call(env)
|
28
|
+
while env['rack.input'].read(4096)
|
29
|
+
end
|
30
|
+
env['rack.early_hints'].call(
|
31
|
+
"Link" => "</style.css>; rel=preload; as=style\n</script.js>; rel=preload"
|
32
|
+
)
|
33
|
+
[200, { 'Content-Type' => 'text/plain' }, ['hello!\n']]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class TestRackAfterReply
|
38
|
+
def initialize
|
39
|
+
@called = false
|
40
|
+
end
|
41
|
+
|
42
|
+
def call(env)
|
43
|
+
while env['rack.input'].read(4096)
|
44
|
+
end
|
45
|
+
|
46
|
+
env["rack.after_reply"] << -> { @called = true }
|
47
|
+
|
48
|
+
[200, { 'Content-Type' => 'text/plain' }, ["after_reply_called: #{@called}"]]
|
49
|
+
rescue Unicorn::ClientShutdown, Unicorn::HttpParserError => e
|
50
|
+
$stderr.syswrite("#{e.class}: #{e.message} #{e.backtrace.empty?}\n")
|
51
|
+
raise e
|
52
|
+
end
|
53
|
+
end
|
26
54
|
|
27
55
|
class WebServerTest < Test::Unit::TestCase
|
28
56
|
|
@@ -80,8 +108,54 @@ def test_preload_app_config
|
|
80
108
|
loader_pid = tmp.sysread(4096).to_i
|
81
109
|
assert_equal $$, loader_pid
|
82
110
|
assert worker_pid != loader_pid
|
83
|
-
|
84
|
-
|
111
|
+
ensure
|
112
|
+
tmp.close!
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_early_hints
|
116
|
+
teardown
|
117
|
+
redirect_test_io do
|
118
|
+
@server = HttpServer.new(TestEarlyHintsHandler.new,
|
119
|
+
:listeners => [ "127.0.0.1:#@port"],
|
120
|
+
:early_hints => true)
|
121
|
+
@server.start
|
122
|
+
end
|
123
|
+
|
124
|
+
sock = tcp_socket('127.0.0.1', @port)
|
125
|
+
sock.syswrite("GET / HTTP/1.0\r\n\r\n")
|
126
|
+
|
127
|
+
responses = sock.read(4096)
|
128
|
+
assert_match %r{\AHTTP/1.[01] 103\b}, responses
|
129
|
+
assert_match %r{^Link: </style\.css>}, responses
|
130
|
+
assert_match %r{^Link: </script\.js>}, responses
|
131
|
+
|
132
|
+
assert_match %r{^HTTP/1.[01] 200\b}, responses
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_after_reply
|
136
|
+
teardown
|
137
|
+
|
138
|
+
redirect_test_io do
|
139
|
+
@server = HttpServer.new(TestRackAfterReply.new,
|
140
|
+
:listeners => [ "127.0.0.1:#@port"])
|
141
|
+
@server.start
|
142
|
+
end
|
143
|
+
|
144
|
+
sock = tcp_socket('127.0.0.1', @port)
|
145
|
+
sock.syswrite("GET / HTTP/1.0\r\n\r\n")
|
146
|
+
|
147
|
+
responses = sock.read(4096)
|
148
|
+
assert_match %r{\AHTTP/1.[01] 200\b}, responses
|
149
|
+
assert_match %r{^after_reply_called: false}, responses
|
150
|
+
|
151
|
+
sock = tcp_socket('127.0.0.1', @port)
|
152
|
+
sock.syswrite("GET / HTTP/1.0\r\n\r\n")
|
153
|
+
|
154
|
+
responses = sock.read(4096)
|
155
|
+
assert_match %r{\AHTTP/1.[01] 200\b}, responses
|
156
|
+
assert_match %r{^after_reply_called: true}, responses
|
157
|
+
|
158
|
+
sock.close
|
85
159
|
end
|
86
160
|
|
87
161
|
def test_broken_app
|
@@ -92,7 +166,7 @@ def test_broken_app
|
|
92
166
|
@server = HttpServer.new(app, :listeners => [ "127.0.0.1:#@port"] )
|
93
167
|
@server.start
|
94
168
|
end
|
95
|
-
sock =
|
169
|
+
sock = tcp_socket('127.0.0.1', @port)
|
96
170
|
sock.syswrite("GET / HTTP/1.0\r\n\r\n")
|
97
171
|
assert_match %r{\AHTTP/1.[01] 500\b}, sock.sysread(4096)
|
98
172
|
assert_nil sock.close
|
@@ -105,7 +179,7 @@ def test_simple_server
|
|
105
179
|
|
106
180
|
def test_client_shutdown_writes
|
107
181
|
bs = 15609315 * rand
|
108
|
-
sock =
|
182
|
+
sock = tcp_socket('127.0.0.1', @port)
|
109
183
|
sock.syswrite("PUT /hello HTTP/1.1\r\n")
|
110
184
|
sock.syswrite("Host: example.com\r\n")
|
111
185
|
sock.syswrite("Transfer-Encoding: chunked\r\n")
|
@@ -132,7 +206,7 @@ def test_client_shutdown_writes
|
|
132
206
|
|
133
207
|
def test_client_shutdown_write_truncates
|
134
208
|
bs = 15609315 * rand
|
135
|
-
sock =
|
209
|
+
sock = tcp_socket('127.0.0.1', @port)
|
136
210
|
sock.syswrite("PUT /hello HTTP/1.1\r\n")
|
137
211
|
sock.syswrite("Host: example.com\r\n")
|
138
212
|
sock.syswrite("Transfer-Encoding: chunked\r\n")
|
@@ -158,7 +232,7 @@ def test_client_shutdown_write_truncates
|
|
158
232
|
|
159
233
|
def test_client_malformed_body
|
160
234
|
bs = 15653984
|
161
|
-
sock =
|
235
|
+
sock = tcp_socket('127.0.0.1', @port)
|
162
236
|
sock.syswrite("PUT /hello HTTP/1.1\r\n")
|
163
237
|
sock.syswrite("Host: example.com\r\n")
|
164
238
|
sock.syswrite("Transfer-Encoding: chunked\r\n")
|
@@ -180,7 +254,7 @@ def test_client_malformed_body
|
|
180
254
|
|
181
255
|
def do_test(string, chunk, close_after=nil, shutdown_delay=0)
|
182
256
|
# Do not use instance variables here, because it needs to be thread safe
|
183
|
-
socket =
|
257
|
+
socket = tcp_socket("127.0.0.1", @port);
|
184
258
|
request = StringIO.new(string)
|
185
259
|
chunks_out = 0
|
186
260
|
|
@@ -225,14 +299,14 @@ def test_logger_changed
|
|
225
299
|
end
|
226
300
|
|
227
301
|
def test_bad_client_400
|
228
|
-
sock =
|
302
|
+
sock = tcp_socket('127.0.0.1', @port)
|
229
303
|
sock.syswrite("GET / HTTP/1.0\r\nHost: foo\rbar\r\n\r\n")
|
230
304
|
assert_match %r{\AHTTP/1.[01] 400\b}, sock.sysread(4096)
|
231
305
|
assert_nil sock.close
|
232
306
|
end
|
233
307
|
|
234
308
|
def test_http_0_9
|
235
|
-
sock =
|
309
|
+
sock = tcp_socket('127.0.0.1', @port)
|
236
310
|
sock.syswrite("GET /hello\r\n")
|
237
311
|
assert_match 'hello!\n', sock.sysread(4096)
|
238
312
|
assert_nil sock.close
|
data/test/unit/test_signals.rb
CHANGED
@@ -52,7 +52,7 @@ def test_worker_dies_on_dead_master
|
|
52
52
|
redirect_test_io { HttpServer.new(app, opts).start.join }
|
53
53
|
}
|
54
54
|
wait_workers_ready("test_stderr.#{pid}.log", 1)
|
55
|
-
sock =
|
55
|
+
sock = tcp_socket('127.0.0.1', @port)
|
56
56
|
sock.syswrite("GET / HTTP/1.0\r\n\r\n")
|
57
57
|
buf = sock.readpartial(4096)
|
58
58
|
assert_nil sock.close
|
@@ -79,7 +79,7 @@ def test_sleepy_kill
|
|
79
79
|
}
|
80
80
|
wr.close
|
81
81
|
wait_workers_ready("test_stderr.#{pid}.log", 1)
|
82
|
-
sock =
|
82
|
+
sock = tcp_socket('127.0.0.1', @port)
|
83
83
|
sock.syswrite("GET / HTTP/1.0\r\n\r\n")
|
84
84
|
buf = rd.readpartial(1)
|
85
85
|
wait_master_ready("test_stderr.#{pid}.log")
|
@@ -102,7 +102,7 @@ def test_timeout_slow_response
|
|
102
102
|
}
|
103
103
|
t0 = Time.now
|
104
104
|
wait_workers_ready("test_stderr.#{pid}.log", 1)
|
105
|
-
sock =
|
105
|
+
sock = tcp_socket('127.0.0.1', @port)
|
106
106
|
sock.syswrite("GET / HTTP/1.0\r\n\r\n")
|
107
107
|
|
108
108
|
buf = nil
|
@@ -114,8 +114,8 @@ def test_timeout_slow_response
|
|
114
114
|
assert_nil buf
|
115
115
|
assert diff > 1.0, "diff was #{diff.inspect}"
|
116
116
|
assert diff < 60.0
|
117
|
-
|
118
|
-
|
117
|
+
ensure
|
118
|
+
Process.kill(:TERM, pid) rescue nil
|
119
119
|
end
|
120
120
|
|
121
121
|
def test_response_write
|
@@ -125,7 +125,7 @@ def test_response_write
|
|
125
125
|
}
|
126
126
|
redirect_test_io { @server = HttpServer.new(app, @server_opts).start }
|
127
127
|
wait_workers_ready("test_stderr.#{$$}.log", 1)
|
128
|
-
sock =
|
128
|
+
sock = tcp_socket('127.0.0.1', @port)
|
129
129
|
sock.syswrite("GET / HTTP/1.0\r\n\r\n")
|
130
130
|
buf = ''
|
131
131
|
header_len = pid = nil
|
@@ -163,13 +163,13 @@ def test_request_read
|
|
163
163
|
redirect_test_io { @server = HttpServer.new(app, @server_opts).start }
|
164
164
|
|
165
165
|
wait_workers_ready("test_stderr.#{$$}.log", 1)
|
166
|
-
sock =
|
166
|
+
sock = tcp_socket('127.0.0.1', @port)
|
167
167
|
sock.syswrite("GET / HTTP/1.0\r\n\r\n")
|
168
168
|
pid = sock.sysread(4096)[/\r\nX-Pid: (\d+)\r\n/, 1].to_i
|
169
169
|
assert_nil sock.close
|
170
170
|
|
171
171
|
assert pid > 0, "pid not positive: #{pid.inspect}"
|
172
|
-
sock =
|
172
|
+
sock = tcp_socket('127.0.0.1', @port)
|
173
173
|
sock.syswrite("PUT / HTTP/1.0\r\n")
|
174
174
|
sock.syswrite("Content-Length: #{@bs * @count}\r\n\r\n")
|
175
175
|
1000.times { Process.kill(:HUP, pid) }
|
@@ -57,8 +57,8 @@ def test_bind_listen_unix
|
|
57
57
|
assert File.readable?(@unix_listener_path), "not readable"
|
58
58
|
assert File.writable?(@unix_listener_path), "not writable"
|
59
59
|
assert_equal 0777, File.umask
|
60
|
-
|
61
|
-
|
60
|
+
ensure
|
61
|
+
File.umask(old_umask)
|
62
62
|
end
|
63
63
|
|
64
64
|
def test_bind_listen_unix_umask
|
@@ -71,8 +71,8 @@ def test_bind_listen_unix_umask
|
|
71
71
|
assert_equal @unix_listener_path, sock_name(@unix_listener)
|
72
72
|
assert_equal 0140700, File.stat(@unix_listener_path).mode
|
73
73
|
assert_equal 0777, File.umask
|
74
|
-
|
75
|
-
|
74
|
+
ensure
|
75
|
+
File.umask(old_umask)
|
76
76
|
end
|
77
77
|
|
78
78
|
def test_bind_listen_unix_idempotent
|
@@ -116,7 +116,7 @@ def test_bind_listen_unix_rebind
|
|
116
116
|
client.syswrite('abcde')
|
117
117
|
exit 0
|
118
118
|
end
|
119
|
-
s =
|
119
|
+
s = unix_socket(@unix_listener_path)
|
120
120
|
IO.select([s])
|
121
121
|
assert_equal 'abcde', s.sysread(5)
|
122
122
|
pid, status = Process.waitpid2(pid)
|
@@ -150,28 +150,31 @@ def test_sock_name
|
|
150
150
|
end
|
151
151
|
|
152
152
|
def test_tcp_defer_accept_default
|
153
|
+
return unless defined?(TCP_DEFER_ACCEPT)
|
153
154
|
port = unused_port @test_addr
|
154
155
|
name = "#@test_addr:#{port}"
|
155
156
|
sock = bind_listen(name)
|
156
157
|
cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0]
|
157
158
|
assert cur >= 1
|
158
|
-
end
|
159
|
+
end
|
159
160
|
|
160
161
|
def test_tcp_defer_accept_disable
|
162
|
+
return unless defined?(TCP_DEFER_ACCEPT)
|
161
163
|
port = unused_port @test_addr
|
162
164
|
name = "#@test_addr:#{port}"
|
163
165
|
sock = bind_listen(name, :tcp_defer_accept => false)
|
164
166
|
cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0]
|
165
167
|
assert_equal 0, cur
|
166
|
-
end
|
168
|
+
end
|
167
169
|
|
168
170
|
def test_tcp_defer_accept_nr
|
171
|
+
return unless defined?(TCP_DEFER_ACCEPT)
|
169
172
|
port = unused_port @test_addr
|
170
173
|
name = "#@test_addr:#{port}"
|
171
174
|
sock = bind_listen(name, :tcp_defer_accept => 60)
|
172
175
|
cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0]
|
173
176
|
assert cur > 1
|
174
|
-
end
|
177
|
+
end
|
175
178
|
|
176
179
|
def test_ipv6only
|
177
180
|
port = begin
|
@@ -186,12 +189,13 @@ def test_ipv6only
|
|
186
189
|
end
|
187
190
|
|
188
191
|
def test_reuseport
|
192
|
+
return unless defined?(Socket::SO_REUSEPORT)
|
189
193
|
port = unused_port @test_addr
|
190
194
|
name = "#@test_addr:#{port}"
|
191
195
|
sock = bind_listen(name, :reuseport => true)
|
192
|
-
cur = sock.getsockopt(
|
196
|
+
cur = sock.getsockopt(:SOL_SOCKET, :SO_REUSEPORT).int
|
193
197
|
assert_operator cur, :>, 0
|
194
198
|
rescue Errno::ENOPROTOOPT
|
195
199
|
# kernel does not support SO_REUSEPORT (older Linux)
|
196
|
-
end
|
200
|
+
end
|
197
201
|
end
|