thin 1.5.1 → 1.6.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 +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:
|