yahns 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Documentation/.gitignore +5 -0
- data/Documentation/GNUmakefile +50 -0
- data/Documentation/yahns-rackup.txt +152 -0
- data/Documentation/yahns.txt +68 -0
- data/Documentation/yahns_config.txt +563 -0
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +14 -7
- data/HACKING +56 -0
- data/INSTALL +8 -0
- data/README +15 -2
- data/Rakefile +2 -2
- data/bin/yahns +1 -2
- data/bin/yahns-rackup +9 -0
- data/examples/yahns_multi.conf.rb +14 -4
- data/examples/yahns_rack_basic.conf.rb +17 -1
- data/extras/README +16 -0
- data/extras/autoindex.rb +151 -0
- data/extras/exec_cgi.rb +108 -0
- data/extras/proxy_pass.rb +210 -0
- data/extras/try_gzip_static.rb +208 -0
- data/lib/yahns.rb +5 -2
- data/lib/yahns/acceptor.rb +64 -22
- data/lib/yahns/cap_input.rb +2 -2
- data/lib/yahns/{client_expire_portable.rb → client_expire_generic.rb} +12 -11
- data/lib/yahns/{client_expire.rb → client_expire_tcpi.rb} +7 -6
- data/lib/yahns/config.rb +107 -22
- data/lib/yahns/daemon.rb +2 -0
- data/lib/yahns/fdmap.rb +28 -9
- data/lib/yahns/http_client.rb +123 -37
- data/lib/yahns/http_context.rb +21 -3
- data/lib/yahns/http_response.rb +80 -19
- data/lib/yahns/log.rb +23 -4
- data/lib/yahns/queue_epoll.rb +20 -9
- data/lib/yahns/queue_quitter.rb +16 -0
- data/lib/yahns/queue_quitter_pipe.rb +24 -0
- data/lib/yahns/rack.rb +0 -1
- data/lib/yahns/rackup_handler.rb +57 -0
- data/lib/yahns/server.rb +189 -59
- data/lib/yahns/server_mp.rb +43 -35
- data/lib/yahns/sigevent_pipe.rb +1 -0
- data/lib/yahns/socket_helper.rb +37 -11
- data/lib/yahns/stream_file.rb +14 -4
- data/lib/yahns/stream_input.rb +13 -7
- data/lib/yahns/tcp_server.rb +7 -0
- data/lib/yahns/tmpio.rb +10 -3
- data/lib/yahns/unix_server.rb +7 -0
- data/lib/yahns/wbuf.rb +19 -2
- data/lib/yahns/wbuf_common.rb +10 -3
- data/lib/yahns/wbuf_str.rb +24 -0
- data/lib/yahns/worker.rb +5 -26
- data/test/helper.rb +15 -5
- data/test/server_helper.rb +37 -1
- data/test/test_bin.rb +17 -8
- data/test/test_buffer_tmpdir.rb +103 -0
- data/test/test_client_expire.rb +71 -35
- data/test/test_client_max_body_size.rb +5 -13
- data/test/test_config.rb +1 -1
- data/test/test_expect_100.rb +176 -0
- data/test/test_extras_autoindex.rb +53 -0
- data/test/test_extras_exec_cgi.rb +81 -0
- data/test/test_extras_exec_cgi.sh +35 -0
- data/test/test_extras_try_gzip_static.rb +177 -0
- data/test/test_input.rb +128 -0
- data/test/test_mt_accept.rb +48 -0
- data/test/test_output_buffering.rb +90 -63
- data/test/test_rack.rb +1 -1
- data/test/test_rack_hijack.rb +2 -6
- data/test/test_reopen_logs.rb +2 -8
- data/test/test_serve_static.rb +104 -8
- data/test/test_server.rb +448 -73
- data/test/test_stream_file.rb +1 -1
- data/test/test_unix_socket.rb +72 -0
- data/test/test_wbuf.rb +20 -17
- data/yahns.gemspec +3 -0
- metadata +57 -5
data/lib/yahns.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
+
$stdout.sync = $stderr.sync = true
|
4
|
+
|
3
5
|
require 'unicorn' # pulls in raindrops, kgio, fcntl, etc, stringio, and logger
|
4
6
|
require 'sleepy_penguin'
|
5
7
|
|
@@ -48,6 +50,9 @@ module Yahns # :nodoc:
|
|
48
50
|
# for client shutdowns/disconnects.
|
49
51
|
class ClientShutdown < EOFError # :nodoc:
|
50
52
|
end
|
53
|
+
|
54
|
+
class ClientTimeout < RuntimeError # :nodoc:
|
55
|
+
end
|
51
56
|
end
|
52
57
|
|
53
58
|
# FIXME: require lazily
|
@@ -56,7 +61,6 @@ require_relative 'yahns/queue_epoll'
|
|
56
61
|
require_relative 'yahns/stream_input'
|
57
62
|
require_relative 'yahns/tee_input'
|
58
63
|
require_relative 'yahns/queue_egg'
|
59
|
-
require_relative 'yahns/client_expire'
|
60
64
|
require_relative 'yahns/http_response'
|
61
65
|
require_relative 'yahns/http_client'
|
62
66
|
require_relative 'yahns/http_context'
|
@@ -65,7 +69,6 @@ require_relative 'yahns/config'
|
|
65
69
|
require_relative 'yahns/tmpio'
|
66
70
|
require_relative 'yahns/worker'
|
67
71
|
require_relative 'yahns/sigevent'
|
68
|
-
require_relative 'yahns/daemon'
|
69
72
|
require_relative 'yahns/socket_helper'
|
70
73
|
require_relative 'yahns/server'
|
71
74
|
require_relative 'yahns/fdmap'
|
data/lib/yahns/acceptor.rb
CHANGED
@@ -1,30 +1,72 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
1
2
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> et. al.
|
2
3
|
# License: GPLv3 or later (see COPYING for details)
|
4
|
+
require_relative 'client_expire_tcpi'
|
5
|
+
require_relative 'client_expire_generic'
|
3
6
|
module Yahns::Acceptor # :nodoc:
|
4
|
-
def
|
5
|
-
|
6
|
-
accept_flags = Kgio::SOCK_NONBLOCK | Kgio::SOCK_CLOEXEC
|
7
|
-
Thread.current.abort_on_exception = true
|
8
|
-
qev_flags = client_class.superclass::QEV_FLAGS
|
7
|
+
def __ac_quit_done?
|
8
|
+
@thrs.delete_if do |t|
|
9
9
|
begin
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
t.join(0.01)
|
11
|
+
rescue
|
12
|
+
! t.alive?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
return false if @thrs[0]
|
16
|
+
close
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
# just keep looping this on every acceptor until the associated thread dies
|
21
|
+
def ac_quit
|
22
|
+
return true unless defined?(@thrs)
|
23
|
+
@thrs.each { |t| t[:yahns_quit] = true }
|
24
|
+
return true if __ac_quit_done?
|
25
|
+
|
26
|
+
@thrs.each do
|
27
|
+
begin
|
28
|
+
# try to connect to kick it out of the blocking accept() syscall
|
29
|
+
killer = Kgio::Socket.start(getsockname)
|
30
|
+
killer.kgio_write("G") # first byte of "GET / HTTP/1.0\r\n\r\n"
|
31
|
+
ensure
|
32
|
+
killer.close if killer
|
33
|
+
end
|
34
|
+
end
|
35
|
+
false # now hope __ac_quit_done? is true next time around
|
36
|
+
rescue SystemCallError
|
37
|
+
return __ac_quit_done?
|
38
|
+
end
|
39
|
+
|
40
|
+
def spawn_acceptor(nr, logger, client_class)
|
41
|
+
@thrs = nr.times.map do
|
42
|
+
Thread.new do
|
43
|
+
queue = client_class.queue
|
44
|
+
t = Thread.current
|
45
|
+
accept_flags = Kgio::SOCK_NONBLOCK | Kgio::SOCK_CLOEXEC
|
46
|
+
qev_flags = client_class.superclass::QEV_FLAGS
|
47
|
+
begin
|
48
|
+
# We want the accept/accept4 syscall to be _blocking_
|
49
|
+
# so it can distribute work evenly between processes
|
50
|
+
if client = kgio_accept(client_class, accept_flags)
|
51
|
+
client.yahns_init
|
14
52
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end while true
|
53
|
+
# it is not safe to touch client in this thread after this,
|
54
|
+
# a worker thread may grab client right away
|
55
|
+
queue.queue_add(client, qev_flags)
|
56
|
+
end
|
57
|
+
rescue Errno::EMFILE, Errno::ENFILE => e
|
58
|
+
logger.error("#{e.message}, consider raising open file limits")
|
59
|
+
queue.fdmap.desperate_expire_for(nil, 5)
|
60
|
+
sleep 1 # let other threads do some work
|
61
|
+
rescue => e
|
62
|
+
Yahns::Log.exception(logger, "accept loop", e)
|
63
|
+
end until t[:yahns_quit]
|
64
|
+
end
|
28
65
|
end
|
29
66
|
end
|
67
|
+
|
68
|
+
def expire_mod
|
69
|
+
(Yahns::TCPServer === self && Yahns.const_defined?(:ClientExpireTCPI)) ?
|
70
|
+
Yahns::ClientExpireTCPI : Yahns::ClientExpireGeneric
|
71
|
+
end
|
30
72
|
end
|
data/lib/yahns/cap_input.rb
CHANGED
@@ -1,38 +1,39 @@
|
|
1
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
-
module Yahns::
|
3
|
+
module Yahns::ClientExpireGeneric # :nodoc:
|
4
4
|
def __timestamp
|
5
5
|
Time.now.to_f
|
6
6
|
end
|
7
7
|
|
8
|
+
def yahns_init
|
9
|
+
super # Yahns::HttpClient#yahns_init
|
10
|
+
@last_io_at = 0
|
11
|
+
end
|
12
|
+
|
8
13
|
def yahns_expire(timeout)
|
9
|
-
return 0 if closed?
|
14
|
+
return 0 if closed?
|
10
15
|
if (__timestamp - @last_io_at) > timeout
|
11
16
|
shutdown
|
12
17
|
1
|
13
18
|
else
|
14
19
|
0
|
15
20
|
end
|
16
|
-
|
21
|
+
# shutdown may race with the shutdown in http_response_done
|
22
|
+
rescue
|
17
23
|
0
|
18
24
|
end
|
19
25
|
|
20
|
-
def
|
21
|
-
@last_io_at = __timestamp
|
22
|
-
super
|
23
|
-
end
|
24
|
-
|
25
|
-
def kgio_write(*args)
|
26
|
+
def kgio_trywrite(*args)
|
26
27
|
@last_io_at = __timestamp
|
27
28
|
super
|
28
29
|
end
|
29
30
|
|
30
|
-
def
|
31
|
+
def kgio_tryread(*args)
|
31
32
|
@last_io_at = __timestamp
|
32
33
|
super
|
33
34
|
end
|
34
35
|
|
35
|
-
def
|
36
|
+
def trysendfile(*args)
|
36
37
|
@last_io_at = __timestamp
|
37
38
|
super
|
38
39
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
+
require 'raindrops'
|
3
4
|
|
4
5
|
# included in Yahns::HttpClient
|
5
6
|
#
|
@@ -7,9 +8,9 @@
|
|
7
8
|
# on idle clients
|
8
9
|
#
|
9
10
|
# we absolutely DO NOT issue IO#close in here, only BasicSocket#shutdown
|
10
|
-
module Yahns::
|
11
|
+
module Yahns::ClientExpireTCPI # :nodoc:
|
11
12
|
def yahns_expire(timeout) # rarely called
|
12
|
-
return 0 if closed?
|
13
|
+
return 0 if closed?
|
13
14
|
|
14
15
|
info = Raindrops::TCP_Info.new(self)
|
15
16
|
return 0 if info.state != 1 # TCP_ESTABLISHED == 1
|
@@ -31,10 +32,10 @@ module Yahns::ClientExpire # :nodoc:
|
|
31
32
|
else
|
32
33
|
0
|
33
34
|
end
|
34
|
-
#
|
35
|
-
# (since those are the most trusted of local clients)
|
36
|
-
# the IO#closed? check is racy
|
35
|
+
# shutdown may race with the shutdown in http_response_done
|
37
36
|
rescue
|
38
37
|
0
|
39
38
|
end
|
40
|
-
|
39
|
+
# FreeBSD has "struct tcp_info", too, but does not support all the fields
|
40
|
+
# Linux does as of FreeBSD 9 (haven't checked FreeBSD 10, yet).
|
41
|
+
end if RUBY_PLATFORM =~ /linux/
|
data/lib/yahns/config.rb
CHANGED
@@ -22,9 +22,10 @@ class Yahns::Config # :nodoc:
|
|
22
22
|
return var if @block == nil
|
23
23
|
msg = "#{var} must be called outside of #{@block.type}"
|
24
24
|
else
|
25
|
-
|
25
|
+
ctx = Array(ctx)
|
26
|
+
return var if @block && ctx.include?(@block.type)
|
26
27
|
msg = @block ? "may not be used inside a #{@block.type} block" :
|
27
|
-
"must be used with a #{ctx} block"
|
28
|
+
"must be used with a #{ctx.join(' or ')} block"
|
28
29
|
end
|
29
30
|
raise ArgumentError, msg
|
30
31
|
end
|
@@ -38,7 +39,7 @@ class Yahns::Config # :nodoc:
|
|
38
39
|
@config_listeners = {} # name/address -> options
|
39
40
|
@app_ctx = []
|
40
41
|
@set = Hash.new(:unset)
|
41
|
-
@qeggs = {}
|
42
|
+
@qeggs = Hash.new { |h,k| h[k] = Yahns::QueueEgg.new }
|
42
43
|
@app_instances = {}
|
43
44
|
|
44
45
|
# set defaults:
|
@@ -73,10 +74,44 @@ class Yahns::Config # :nodoc:
|
|
73
74
|
end
|
74
75
|
end
|
75
76
|
|
76
|
-
def
|
77
|
-
|
78
|
-
var =
|
77
|
+
def shutdown_timeout(sec)
|
78
|
+
var = _check_in_block(nil, :shutdown_timeout)
|
79
|
+
@set[var] = _check_num(var, sec, 0)
|
80
|
+
end
|
81
|
+
|
82
|
+
def worker_processes(nr, &blk)
|
83
|
+
var =_check_in_block(nil, :worker_processes)
|
79
84
|
@set[var] = _check_int(var, nr, 1)
|
85
|
+
if block_given?
|
86
|
+
@block = CfgBlock.new(var, nil)
|
87
|
+
instance_eval(&blk)
|
88
|
+
@block = nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
%w(atfork_prepare atfork_parent atfork_child).each do |fn|
|
93
|
+
eval(
|
94
|
+
%Q(def #{fn}(*args, &blk);) <<
|
95
|
+
%Q( _check_in_block([:worker_processes,:app], :#{fn});) <<
|
96
|
+
%Q( _add_hook(:#{fn}, block_given? ? blk : args[0]);) <<
|
97
|
+
%Q(end)
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
def before_exec(&blk)
|
102
|
+
var = _check_in_block(nil, :before_exec)
|
103
|
+
@set[var] = (block_given? ? blk : args[0])
|
104
|
+
end
|
105
|
+
|
106
|
+
def _add_hook(var, my_proc)
|
107
|
+
Proc === my_proc or
|
108
|
+
raise ArgumentError, "invalid type: #{var}=#{my_proc.inspect}"
|
109
|
+
|
110
|
+
# this sets:
|
111
|
+
# :atfork_prepare, :atfork_parent, :atfork_child
|
112
|
+
key = var.to_sym
|
113
|
+
@set[key] = [] unless @set.include?(key)
|
114
|
+
@set[key] << my_proc
|
80
115
|
end
|
81
116
|
|
82
117
|
# sets the +path+ for the PID file of the yahns master process
|
@@ -104,7 +139,7 @@ class Yahns::Config # :nodoc:
|
|
104
139
|
# for error checking and cannot be undone by unsetting it in the
|
105
140
|
# configuration file and reloading.
|
106
141
|
def working_directory(path)
|
107
|
-
var = :working_directory
|
142
|
+
var = _check_in_block(nil, :working_directory)
|
108
143
|
@app_ctx.empty? or
|
109
144
|
raise ArgumentError, "#{var} must be declared before any apps"
|
110
145
|
|
@@ -127,7 +162,7 @@ class Yahns::Config # :nodoc:
|
|
127
162
|
# if the Worker#user method is not called in the after_fork hooks
|
128
163
|
# +group+ is optional and will not change if unspecified.
|
129
164
|
def user(user, group = nil)
|
130
|
-
var = :user
|
165
|
+
var = _check_in_block(nil, :user)
|
131
166
|
@block and raise "#{var} is not valid inside #{@block.type}"
|
132
167
|
# raises ArgumentError on invalid user/group
|
133
168
|
Etc.getpwnam(user)
|
@@ -151,12 +186,17 @@ class Yahns::Config # :nodoc:
|
|
151
186
|
address = expand_addr(address)
|
152
187
|
String === address or
|
153
188
|
raise ArgumentError, "address=#{address.inspect} must be a string"
|
154
|
-
[ :umask, :backlog
|
189
|
+
[ :umask, :backlog ].each do |key|
|
190
|
+
# :backlog may be negative on some OSes
|
155
191
|
value = options[key] or next
|
156
192
|
Integer === value or
|
157
193
|
raise ArgumentError, "#{var}: not an integer: #{key}=#{value.inspect}"
|
158
194
|
end
|
159
|
-
[ :
|
195
|
+
[ :sndbuf, :rcvbuf, :threads ].each do |key|
|
196
|
+
value = options[key] and _check_int(key, value, 1)
|
197
|
+
end
|
198
|
+
|
199
|
+
[ :ipv6only, :reuseport ].each do |key|
|
160
200
|
(value = options[key]).nil? and next
|
161
201
|
[ true, false ].include?(value) or
|
162
202
|
raise ArgumentError, "#{var}: not boolean: #{key}=#{value.inspect}"
|
@@ -197,16 +237,33 @@ class Yahns::Config # :nodoc:
|
|
197
237
|
/:/ =~ addr ? "[#{addr}]:#{port}" : "#{addr}:#{port}"
|
198
238
|
end
|
199
239
|
|
200
|
-
def queue(
|
240
|
+
def queue(*args, &block)
|
201
241
|
var = :queue
|
202
|
-
qegg = @qeggs[name] ||= Yahns::QueueEgg.new
|
203
242
|
prev_block = @block
|
204
|
-
|
243
|
+
if prev_block
|
244
|
+
_check_in_block(:app, var)
|
245
|
+
if block_given?
|
246
|
+
args.size == 0 or
|
247
|
+
raise ArgumentError,
|
248
|
+
"queues defined with a block inside app must not have names"
|
249
|
+
name = @block
|
250
|
+
else
|
251
|
+
name = args[0] or
|
252
|
+
raise ArgumentError, "queue must be given a name if no block given"
|
253
|
+
end
|
254
|
+
else
|
255
|
+
name = args[0] || :default
|
256
|
+
end
|
257
|
+
args.size > 1 and
|
258
|
+
raise ArgumentError, "queue only takes one name argument"
|
259
|
+
qegg = @qeggs[name]
|
205
260
|
if block_given?
|
206
261
|
@block = CfgBlock.new(:queue, qegg)
|
207
262
|
instance_eval(&block)
|
208
263
|
@block = prev_block
|
209
264
|
end
|
265
|
+
|
266
|
+
# associate the queue if we're inside an app
|
210
267
|
prev_block.ctx.qegg = qegg if prev_block
|
211
268
|
end
|
212
269
|
|
@@ -226,12 +283,19 @@ class Yahns::Config # :nodoc:
|
|
226
283
|
n
|
227
284
|
end
|
228
285
|
|
286
|
+
def _check_num(var, n, min)
|
287
|
+
Numeric === n or raise ArgumentError, "not a number: #{var}=#{n.inspect}"
|
288
|
+
n >= min or raise ArgumentError, "too low (< #{min}): #{var}=#{n.inspect}"
|
289
|
+
n
|
290
|
+
end
|
291
|
+
|
229
292
|
# global
|
230
293
|
def client_expire_threshold(val)
|
231
294
|
var = _check_in_block(nil, :client_expire_threshold)
|
232
295
|
case val
|
233
296
|
when Float
|
234
|
-
val
|
297
|
+
(val > 0 && val <= 1.0) or
|
298
|
+
raise ArgumentError, "#{var} must be > 0 and <= 1.0 if a ratio"
|
235
299
|
when Integer
|
236
300
|
else
|
237
301
|
raise ArgumentError, "#{var} must be a float or integer"
|
@@ -270,9 +334,7 @@ class Yahns::Config # :nodoc:
|
|
270
334
|
end
|
271
335
|
|
272
336
|
# boolean config directives for app
|
273
|
-
%w(check_client_connection
|
274
|
-
output_buffering
|
275
|
-
persistent_connections).each do |_v|
|
337
|
+
%w(check_client_connection persistent_connections).each do |_v|
|
276
338
|
eval(
|
277
339
|
%Q(def #{_v}(bool);) <<
|
278
340
|
%Q( _check_in_block(:app, :#{_v});) <<
|
@@ -281,13 +343,27 @@ class Yahns::Config # :nodoc:
|
|
281
343
|
)
|
282
344
|
end
|
283
345
|
|
346
|
+
def output_buffering(bool, opts = {})
|
347
|
+
var = _check_in_block(:app, :output_buffering)
|
348
|
+
@block.ctx.__send__("#{var}=", _check_bool(var, bool))
|
349
|
+
tmpdir = opts[:tmpdir] and
|
350
|
+
@block.ctx.output_buffer_tmpdir = _check_tmpdir(var, tmpdir)
|
351
|
+
end
|
352
|
+
|
353
|
+
def _check_tmpdir(var, path)
|
354
|
+
File.directory?(path) or
|
355
|
+
raise ArgumentError, "#{var} tmpdir: #{path} is not a directory"
|
356
|
+
File.writable?(path) or
|
357
|
+
raise ArgumentError, "#{var} tmpdir: #{path} is not writable"
|
358
|
+
path
|
359
|
+
end
|
360
|
+
|
284
361
|
# integer config directives for app
|
285
362
|
{
|
286
363
|
# config name, minimum value
|
287
364
|
client_body_buffer_size: 1,
|
288
365
|
client_header_buffer_size: 1,
|
289
366
|
client_max_header_size: 1,
|
290
|
-
client_timeout: 0,
|
291
367
|
}.each do |_v,minval|
|
292
368
|
eval(
|
293
369
|
%Q(def #{_v}(val);) <<
|
@@ -297,18 +373,25 @@ class Yahns::Config # :nodoc:
|
|
297
373
|
)
|
298
374
|
end
|
299
375
|
|
376
|
+
def client_timeout(val)
|
377
|
+
var = _check_in_block(:app, :client_timeout)
|
378
|
+
@block.ctx.__send__("#{var}=", _check_num(var, val, 0))
|
379
|
+
end
|
380
|
+
|
300
381
|
def client_max_body_size(val)
|
301
382
|
var = _check_in_block(:app, :client_max_body_size)
|
302
383
|
val = _check_int(var, val, 0) if val != nil
|
303
384
|
@block.ctx.__send__("#{var}=", val)
|
304
385
|
end
|
305
386
|
|
306
|
-
def input_buffering(val)
|
387
|
+
def input_buffering(val, opts = {})
|
307
388
|
var = _check_in_block(:app, :input_buffering)
|
308
389
|
ok = [ :lazy, true, false ]
|
309
390
|
ok.include?(val) or
|
310
391
|
raise ArgumentError, "`#{var}' must be one of: #{ok.inspect}"
|
311
392
|
@block.ctx.__send__("#{var}=", val)
|
393
|
+
tmpdir = opts[:tmpdir] and
|
394
|
+
@block.ctx.input_buffer_tmpdir = _check_tmpdir(var, tmpdir)
|
312
395
|
end
|
313
396
|
|
314
397
|
# used to configure rack.errors destination
|
@@ -335,14 +418,16 @@ class Yahns::Config # :nodoc:
|
|
335
418
|
@set[key] = path = "/dev/null"
|
336
419
|
end
|
337
420
|
File.open(path, 'a') { |fp| io.reopen(fp) } if String === path
|
338
|
-
io.
|
421
|
+
io.sync = true
|
339
422
|
end
|
340
423
|
|
341
|
-
[ :logger, :pid, :worker_processes
|
424
|
+
[ :logger, :pid, :worker_processes, :user, :shutdown_timeout, :before_exec,
|
425
|
+
:atfork_prepare, :atfork_parent, :atfork_child
|
426
|
+
].each do |var|
|
342
427
|
val = @set[var]
|
343
428
|
server.__send__("#{var}=", val) if val != :unset
|
344
429
|
end
|
345
|
-
|
430
|
+
|
346
431
|
@app_ctx.each { |app| app.logger ||= server.logger }
|
347
432
|
end
|
348
433
|
end
|