thin 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +11 -0
- data/ext/thin_parser/common.rl +8 -4
- data/ext/thin_parser/parser.c +531 -328
- data/ext/thin_parser/parser.rl +9 -9
- data/ext/thin_parser/thin.c +3 -4
- data/lib/thin/backends/base.rb +13 -3
- data/lib/thin/command.rb +2 -2
- data/lib/thin/connection.rb +19 -15
- data/lib/thin/controllers/cluster.rb +4 -4
- data/lib/thin/controllers/controller.rb +5 -4
- data/lib/thin/controllers/service.rb +16 -16
- data/lib/thin/daemonizing.rb +10 -12
- data/lib/thin/logging.rb +144 -33
- data/lib/thin/request.rb +7 -1
- data/lib/thin/runner.rb +23 -6
- data/lib/thin/server.rb +47 -33
- data/lib/thin/stats.rb +1 -1
- data/lib/thin/version.rb +3 -3
- metadata +17 -26
data/lib/thin/request.rb
CHANGED
@@ -20,6 +20,7 @@ module Thin
|
|
20
20
|
# Freeze some HTTP header names & values
|
21
21
|
SERVER_SOFTWARE = 'SERVER_SOFTWARE'.freeze
|
22
22
|
SERVER_NAME = 'SERVER_NAME'.freeze
|
23
|
+
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
|
23
24
|
LOCALHOST = 'localhost'.freeze
|
24
25
|
HTTP_VERSION = 'HTTP_VERSION'.freeze
|
25
26
|
HTTP_1_0 = 'HTTP/1.0'.freeze
|
@@ -28,6 +29,7 @@ module Thin
|
|
28
29
|
CONNECTION = 'HTTP_CONNECTION'.freeze
|
29
30
|
KEEP_ALIVE_REGEXP = /\bkeep-alive\b/i.freeze
|
30
31
|
CLOSE_REGEXP = /\bclose\b/i.freeze
|
32
|
+
HEAD = 'HEAD'.freeze
|
31
33
|
|
32
34
|
# Freeze some Rack header names
|
33
35
|
RACK_INPUT = 'rack.input'.freeze
|
@@ -128,7 +130,7 @@ module Thin
|
|
128
130
|
def threaded=(value)
|
129
131
|
@env[RACK_MULTITHREAD] = value
|
130
132
|
end
|
131
|
-
|
133
|
+
|
132
134
|
def async_callback=(callback)
|
133
135
|
@env[ASYNC_CALLBACK] = callback
|
134
136
|
@env[ASYNC_CLOSE] = EventMachine::DefaultDeferrable.new
|
@@ -138,6 +140,10 @@ module Thin
|
|
138
140
|
@async_close ||= @env[ASYNC_CLOSE]
|
139
141
|
end
|
140
142
|
|
143
|
+
def head?
|
144
|
+
@env[REQUEST_METHOD] == HEAD
|
145
|
+
end
|
146
|
+
|
141
147
|
# Close any resource used by the request
|
142
148
|
def close
|
143
149
|
@body.delete if @body.class == Tempfile
|
data/lib/thin/runner.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'logger'
|
1
2
|
require 'optparse'
|
2
3
|
require 'yaml'
|
3
4
|
|
@@ -37,12 +38,13 @@ module Thin
|
|
37
38
|
:address => '0.0.0.0',
|
38
39
|
:port => Server::DEFAULT_PORT,
|
39
40
|
:timeout => Server::DEFAULT_TIMEOUT,
|
40
|
-
:log => 'log/thin.log',
|
41
|
+
:log => File.join(Dir.pwd, 'log/thin.log'),
|
41
42
|
:pid => 'tmp/pids/thin.pid',
|
42
43
|
:max_conns => Server::DEFAULT_MAXIMUM_CONNECTIONS,
|
43
44
|
:max_persistent_conns => Server::DEFAULT_MAXIMUM_PERSISTENT_CONNECTIONS,
|
44
45
|
:require => [],
|
45
|
-
:wait => Controllers::Cluster::DEFAULT_WAIT_TIME
|
46
|
+
:wait => Controllers::Cluster::DEFAULT_WAIT_TIME,
|
47
|
+
:threadpool_size => 20
|
46
48
|
}
|
47
49
|
|
48
50
|
parse!
|
@@ -124,6 +126,8 @@ module Thin
|
|
124
126
|
"(default: #{@options[:max_persistent_conns]})") { |num| @options[:max_persistent_conns] = num.to_i }
|
125
127
|
opts.on( "--threaded", "Call the Rack application in threads " +
|
126
128
|
"[experimental]") { @options[:threaded] = true }
|
129
|
+
opts.on( "--threadpool-size NUM", "Sets the size of the EventMachine threadpool.",
|
130
|
+
"(default: #{@options[:threadpool_size]})") { |num| @options[:threadpool_size] = num.to_i }
|
127
131
|
opts.on( "--no-epoll", "Disable the use of epoll") { @options[:no_epoll] = true } if Thin.linux?
|
128
132
|
|
129
133
|
opts.separator ""
|
@@ -131,7 +135,7 @@ module Thin
|
|
131
135
|
|
132
136
|
opts.on_tail("-r", "--require FILE", "require the library") { |file| @options[:require] << file }
|
133
137
|
opts.on_tail("-q", "--quiet", "Silence all logging") { @options[:quiet] = true }
|
134
|
-
opts.on_tail("-D", "--debug", "
|
138
|
+
opts.on_tail("-D", "--debug", "Enable debug logging") { @options[:debug] = true }
|
135
139
|
opts.on_tail("-V", "--trace", "Set tracing on (log raw request/response)") { @options[:trace] = true }
|
136
140
|
opts.on_tail("-h", "--help", "Show this message") { puts opts; exit }
|
137
141
|
opts.on_tail('-v', '--version', "Show version") { puts Thin::SERVER; exit }
|
@@ -172,9 +176,22 @@ module Thin
|
|
172
176
|
Dir.chdir(@options[:chdir]) unless CONFIGLESS_COMMANDS.include?(@command)
|
173
177
|
|
174
178
|
@options[:require].each { |r| ruby_require r }
|
175
|
-
|
176
|
-
|
177
|
-
|
179
|
+
|
180
|
+
# Setup the logger
|
181
|
+
if @options[:quiet]
|
182
|
+
Logging.silent = true
|
183
|
+
else
|
184
|
+
logger = Logger.new(STDOUT)
|
185
|
+
logger.level = Logger::INFO
|
186
|
+
logger.level = Logger::DEBUG if @options[:debug]
|
187
|
+
logger.formatter = Logging::SimpleFormatter.new
|
188
|
+
Logging.logger = logger
|
189
|
+
end
|
190
|
+
|
191
|
+
if @options[:trace]
|
192
|
+
# Trace raw requests/responses
|
193
|
+
Logging.trace_logger = Logging.logger
|
194
|
+
end
|
178
195
|
|
179
196
|
controller = case
|
180
197
|
when cluster? then Controllers::Cluster.new(@options)
|
data/lib/thin/server.rb
CHANGED
@@ -41,9 +41,12 @@ module Thin
|
|
41
41
|
# end
|
42
42
|
#
|
43
43
|
# == Controlling with signals
|
44
|
-
# * QUIT: Gracefull shutdown (see Server#stop)
|
45
44
|
# * INT and TERM: Force shutdown (see Server#stop!)
|
46
|
-
#
|
45
|
+
# * TERM & QUIT calls +stop+ to shutdown gracefully.
|
46
|
+
# * HUP calls +restart+ to ... surprise, restart!
|
47
|
+
# * USR1 reopen log files.
|
48
|
+
# Signals are processed at one second intervals.
|
49
|
+
# Disable signals by passing <tt>:signals => false</tt>.
|
47
50
|
#
|
48
51
|
class Server
|
49
52
|
include Logging
|
@@ -80,7 +83,7 @@ module Thin
|
|
80
83
|
def_delegators :backend, :maximum_persistent_connections, :maximum_persistent_connections=
|
81
84
|
|
82
85
|
# Allow using threads in the backend.
|
83
|
-
def_delegators :backend, :threaded?, :threaded=
|
86
|
+
def_delegators :backend, :threaded?, :threaded=, :threadpool_size, :threadpool_size=
|
84
87
|
|
85
88
|
# Allow using SSL in the backend.
|
86
89
|
def_delegators :backend, :ssl?, :ssl=, :ssl_options=
|
@@ -130,7 +133,7 @@ module Thin
|
|
130
133
|
# If in debug mode, wrap in logger adapter
|
131
134
|
@app = Rack::CommonLogger.new(@app) if Logging.debug?
|
132
135
|
|
133
|
-
setup_signals
|
136
|
+
@setup_signals = options[:signals] != false
|
134
137
|
end
|
135
138
|
|
136
139
|
# Lil' shortcut to turn this:
|
@@ -149,14 +152,14 @@ module Thin
|
|
149
152
|
def start
|
150
153
|
raise ArgumentError, 'app required' unless @app
|
151
154
|
|
152
|
-
|
153
|
-
|
154
|
-
trace
|
155
|
+
log_info "Thin web server (v#{VERSION::STRING} codename #{VERSION::CODENAME})"
|
156
|
+
log_debug "Debugging ON"
|
157
|
+
trace "Tracing ON"
|
155
158
|
|
156
|
-
|
157
|
-
|
159
|
+
log_info "Maximum connections set to #{@backend.maximum_connections}"
|
160
|
+
log_info "Listening on #{@backend}, CTRL+C to stop"
|
158
161
|
|
159
|
-
@backend.start
|
162
|
+
@backend.start { setup_signals if @setup_signals }
|
160
163
|
end
|
161
164
|
alias :start! :start
|
162
165
|
|
@@ -169,8 +172,8 @@ module Thin
|
|
169
172
|
if running?
|
170
173
|
@backend.stop
|
171
174
|
unless @backend.empty?
|
172
|
-
|
173
|
-
|
175
|
+
log_info "Waiting for #{@backend.size} connection(s) to finish, "\
|
176
|
+
"can take up to #{timeout} sec, CTRL+C to stop now"
|
174
177
|
end
|
175
178
|
else
|
176
179
|
stop!
|
@@ -182,7 +185,7 @@ module Thin
|
|
182
185
|
# This doesn't wait for connection to finish their work and send data.
|
183
186
|
# All current requests will be dropped.
|
184
187
|
def stop!
|
185
|
-
|
188
|
+
log_info "Stopping ..."
|
186
189
|
|
187
190
|
@backend.stop!
|
188
191
|
end
|
@@ -192,7 +195,7 @@ module Thin
|
|
192
195
|
def reopen_log
|
193
196
|
return unless log_file
|
194
197
|
file = File.expand_path(log_file)
|
195
|
-
|
198
|
+
log_info "Reopening log file: #{file}"
|
196
199
|
Daemonize.redirect_io(file)
|
197
200
|
end
|
198
201
|
|
@@ -217,25 +220,36 @@ module Thin
|
|
217
220
|
@backend.running?
|
218
221
|
end
|
219
222
|
|
220
|
-
# deamonizing kills our HUP signal, so we set them again
|
221
|
-
def after_daemonize
|
222
|
-
setup_signals
|
223
|
-
end
|
224
|
-
|
225
223
|
protected
|
226
|
-
# Register signals:
|
227
|
-
# * TERM & QUIT calls +stop+ to shutdown gracefully.
|
228
|
-
# * INT calls <tt>stop!</tt> to force shutdown.
|
229
|
-
# * HUP calls <tt>restart</tt> to ... surprise, restart!
|
230
|
-
# * USR1 reopen log files.
|
231
224
|
def setup_signals
|
232
|
-
trap
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
trap(
|
225
|
+
# Queue up signals so they are processed in non-trap context
|
226
|
+
# using a EM timer.
|
227
|
+
@signal_queue ||= []
|
228
|
+
|
229
|
+
%w( INT TERM ).each do |signal|
|
230
|
+
trap(signal) { @signal_queue.push signal }
|
231
|
+
end
|
232
|
+
# *nix only signals
|
233
|
+
%w( QUIT HUP USR1 ).each do |signal|
|
234
|
+
trap(signal) { @signal_queue.push signal }
|
235
|
+
end unless Thin.win?
|
236
|
+
|
237
|
+
# Signals are processed at one second intervals.
|
238
|
+
@signal_timer ||= EM.add_periodic_timer(1) { handle_signals }
|
239
|
+
end
|
240
|
+
|
241
|
+
def handle_signals
|
242
|
+
case @signal_queue.shift
|
243
|
+
when 'INT'
|
244
|
+
stop!
|
245
|
+
when 'TERM', 'QUIT'
|
246
|
+
stop
|
247
|
+
when 'HUP'
|
248
|
+
restart
|
249
|
+
when 'USR1'
|
250
|
+
reopen_log
|
238
251
|
end
|
252
|
+
EM.next_tick { handle_signals } unless @signal_queue.empty?
|
239
253
|
end
|
240
254
|
|
241
255
|
def select_backend(host, port, options)
|
@@ -261,10 +275,10 @@ module Thin
|
|
261
275
|
begin
|
262
276
|
require 'cgi_multipart_eof_fix'
|
263
277
|
rescue LoadError
|
264
|
-
|
265
|
-
|
278
|
+
log_error "Ruby 1.8.5 is not secure please install cgi_multipart_eof_fix:"
|
279
|
+
log_error "gem install cgi_multipart_eof_fix"
|
266
280
|
end
|
267
281
|
end
|
268
282
|
end
|
269
283
|
end
|
270
|
-
end
|
284
|
+
end
|
data/lib/thin/stats.rb
CHANGED
data/lib/thin/version.rb
CHANGED
@@ -5,12 +5,12 @@ module Thin
|
|
5
5
|
|
6
6
|
module VERSION #:nodoc:
|
7
7
|
MAJOR = 1
|
8
|
-
MINOR =
|
9
|
-
TINY =
|
8
|
+
MINOR = 6
|
9
|
+
TINY = 0
|
10
10
|
|
11
11
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
12
12
|
|
13
|
-
CODENAME = "
|
13
|
+
CODENAME = "Greek Yogurt".freeze
|
14
14
|
|
15
15
|
RACK = [1, 0].freeze # Rack protocol version
|
16
16
|
end
|
metadata
CHANGED
@@ -1,62 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.6.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Marc-Andre Cournoyer
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-10-02 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rack
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.
|
19
|
+
version: 1.5.0
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: 1.
|
26
|
+
version: 1.5.0
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: eventmachine
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
|
-
version: 0.
|
33
|
+
version: 1.0.0
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
|
-
version: 0.
|
40
|
+
version: 1.0.0
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: daemons
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: 1.0.9
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: 1.0.9
|
62
55
|
description: A thin and fast web server
|
@@ -118,27 +111,25 @@ files:
|
|
118
111
|
homepage: http://code.macournoyer.com/thin/
|
119
112
|
licenses:
|
120
113
|
- Ruby
|
114
|
+
metadata: {}
|
121
115
|
post_install_message:
|
122
116
|
rdoc_options: []
|
123
117
|
require_paths:
|
124
118
|
- lib
|
125
119
|
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
-
none: false
|
127
120
|
requirements:
|
128
|
-
- -
|
121
|
+
- - '>='
|
129
122
|
- !ruby/object:Gem::Version
|
130
123
|
version: 1.8.5
|
131
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
-
none: false
|
133
125
|
requirements:
|
134
|
-
- -
|
126
|
+
- - '>='
|
135
127
|
- !ruby/object:Gem::Version
|
136
128
|
version: '0'
|
137
129
|
requirements: []
|
138
130
|
rubyforge_project: thin
|
139
|
-
rubygems_version:
|
131
|
+
rubygems_version: 2.0.0
|
140
132
|
signing_key:
|
141
|
-
specification_version:
|
133
|
+
specification_version: 4
|
142
134
|
summary: A thin and fast web server
|
143
135
|
test_files: []
|
144
|
-
has_rdoc:
|