passenger 3.0.19 → 3.0.21
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data.tar.gz.asc +12 -0
- data/NEWS +12 -0
- data/bin/passenger-install-nginx-module +3 -4
- data/doc/Architectural overview.html +90 -49
- data/doc/Security of user switching support.html +66 -35
- data/doc/Users guide Apache.html +506 -329
- data/doc/Users guide Apache.idmap.txt +55 -52
- data/doc/Users guide Nginx.html +380 -241
- data/doc/Users guide Nginx.idmap.txt +52 -52
- data/doc/Users guide Standalone.html +48 -24
- data/ext/common/Constants.h +1 -1
- data/ext/libev/configure +3545 -4964
- data/lib/phusion_passenger.rb +2 -2
- data/lib/phusion_passenger/abstract_request_handler.rb +7 -1
- data/lib/phusion_passenger/dependencies.rb +12 -20
- data/lib/phusion_passenger/platform_info.rb +17 -25
- data/lib/phusion_passenger/platform_info/apache.rb +1 -10
- data/lib/phusion_passenger/platform_info/ruby.rb +97 -37
- data/lib/phusion_passenger/rack/request_handler.rb +20 -1
- data/lib/phusion_passenger/standalone/command.rb +5 -4
- data/lib/phusion_passenger/standalone/runtime_installer.rb +4 -5
- metadata +69 -86
- metadata.gz.asc +12 -0
- data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
data/lib/phusion_passenger.rb
CHANGED
@@ -25,9 +25,9 @@ module PhusionPassenger
|
|
25
25
|
###### Version numbers ######
|
26
26
|
|
27
27
|
# Phusion Passenger version number. Don't forget to edit ext/common/Constants.h too.
|
28
|
-
VERSION_STRING = '3.0.
|
28
|
+
VERSION_STRING = '3.0.21'
|
29
29
|
|
30
|
-
PREFERRED_NGINX_VERSION = '1.2.
|
30
|
+
PREFERRED_NGINX_VERSION = '1.2.9'
|
31
31
|
PREFERRED_PCRE_VERSION = '8.31'
|
32
32
|
STANDALONE_INTERFACE_VERSION = 1
|
33
33
|
|
@@ -453,6 +453,9 @@ private
|
|
453
453
|
trap(signal, handler)
|
454
454
|
end
|
455
455
|
end
|
456
|
+
|
457
|
+
class IgnoreException < StandardError
|
458
|
+
end
|
456
459
|
|
457
460
|
def accept_and_process_next_request(socket_wrapper, channel, buffer)
|
458
461
|
select_result = select(@selectable_sockets, nil, nil, @select_timeout)
|
@@ -509,17 +512,20 @@ private
|
|
509
512
|
|
510
513
|
if headers
|
511
514
|
prepare_request(headers)
|
515
|
+
ignore = false
|
512
516
|
begin
|
513
517
|
if headers[REQUEST_METHOD] == PING
|
514
518
|
process_ping(headers, input_stream, connection)
|
515
519
|
else
|
516
520
|
process_request(headers, input_stream, connection, full_http_response)
|
517
521
|
end
|
522
|
+
rescue IgnoreException
|
523
|
+
ignore = true
|
518
524
|
rescue Exception
|
519
525
|
has_error = true
|
520
526
|
raise
|
521
527
|
ensure
|
522
|
-
finalize_request(headers, has_error)
|
528
|
+
finalize_request(headers, has_error) if !ignore
|
523
529
|
end
|
524
530
|
end
|
525
531
|
return true
|
@@ -22,6 +22,7 @@
|
|
22
22
|
# THE SOFTWARE.
|
23
23
|
|
24
24
|
require 'rbconfig'
|
25
|
+
require 'tmpdir'
|
25
26
|
require 'phusion_passenger'
|
26
27
|
require 'phusion_passenger/packaging'
|
27
28
|
require 'phusion_passenger/platform_info'
|
@@ -117,6 +118,12 @@ module Dependencies # :nodoc: all
|
|
117
118
|
end
|
118
119
|
end
|
119
120
|
|
121
|
+
def self.create_temp_files(name1, name2, dir = PlatformInfo.tmpexedir)
|
122
|
+
Dir.mktmpdir("passenger.", dir) do |subdir|
|
123
|
+
yield "#{subdir}/#{name1}", "#{subdir}/#{name2}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
120
127
|
GCC = Dependency.new do |dep|
|
121
128
|
dep.name = "GNU C++ compiler"
|
122
129
|
dep.define_checker do |result|
|
@@ -456,9 +463,7 @@ module Dependencies # :nodoc: all
|
|
456
463
|
Curl_Dev = Dependency.new do |dep|
|
457
464
|
dep.name = "Curl development headers with SSL support"
|
458
465
|
dep.define_checker do |result|
|
459
|
-
|
460
|
-
output_file = "#{PlatformInfo.tmpexedir}/passenger-curl-check"
|
461
|
-
begin
|
466
|
+
Dependencies.create_temp_files("check.c", "check") do |source_file, output_file|
|
462
467
|
found = true
|
463
468
|
File.open(source_file, 'w') do |f|
|
464
469
|
f.puts("#include <curl/curl.h>")
|
@@ -482,9 +487,6 @@ module Dependencies # :nodoc: all
|
|
482
487
|
found = false
|
483
488
|
end
|
484
489
|
result.found(found)
|
485
|
-
ensure
|
486
|
-
File.unlink(source_file) rescue nil
|
487
|
-
File.unlink(output_file) rescue nil
|
488
490
|
end
|
489
491
|
end
|
490
492
|
dep.install_instructions = "Please download Curl from <b>http://curl.haxx.se/libcurl</b> " +
|
@@ -514,22 +516,17 @@ module Dependencies # :nodoc: all
|
|
514
516
|
OpenSSL_Dev = Dependency.new do |dep|
|
515
517
|
dep.name = "OpenSSL development headers"
|
516
518
|
dep.define_checker do |result|
|
517
|
-
|
518
|
-
object_file = "#{PlatformInfo.tmpexedir}/passenger-openssl-check.o"
|
519
|
-
begin
|
519
|
+
Dependencies.create_temp_files("check.c", "check.o") do |source_file, output_file|
|
520
520
|
File.open(source_file, 'w') do |f|
|
521
521
|
f.write("#include <openssl/ssl.h>")
|
522
522
|
end
|
523
523
|
Dir.chdir(File.dirname(source_file)) do
|
524
|
-
if system("(gcc #{ENV['CFLAGS']} -c '#{source_file}') >/dev/null 2>/dev/null")
|
524
|
+
if system("(gcc #{ENV['CFLAGS']} -c '#{source_file}' -o '#{output_file}') >/dev/null 2>/dev/null")
|
525
525
|
result.found
|
526
526
|
else
|
527
527
|
result.not_found
|
528
528
|
end
|
529
529
|
end
|
530
|
-
ensure
|
531
|
-
File.unlink(source_file) rescue nil
|
532
|
-
File.unlink(object_file) rescue nil
|
533
530
|
end
|
534
531
|
end
|
535
532
|
if RUBY_PLATFORM =~ /linux/
|
@@ -546,22 +543,17 @@ module Dependencies # :nodoc: all
|
|
546
543
|
Zlib_Dev = Dependency.new do |dep|
|
547
544
|
dep.name = "Zlib development headers"
|
548
545
|
dep.define_checker do |result|
|
549
|
-
|
550
|
-
object_file = "#{PlatformInfo.tmpexedir}/zlib-check.o"
|
551
|
-
begin
|
546
|
+
Dependencies.create_temp_files("check.c", "check.o") do |source_file, output_file|
|
552
547
|
File.open(source_file, 'w') do |f|
|
553
548
|
f.write("#include <zlib.h>")
|
554
549
|
end
|
555
550
|
Dir.chdir(File.dirname(source_file)) do
|
556
|
-
if system("(g++ -c
|
551
|
+
if system("(g++ -c '#{source_file}' -o '#{output_file}') >/dev/null 2>/dev/null")
|
557
552
|
result.found
|
558
553
|
else
|
559
554
|
result.not_found
|
560
555
|
end
|
561
556
|
end
|
562
|
-
ensure
|
563
|
-
File.unlink(source_file) rescue nil
|
564
|
-
File.unlink(object_file) rescue nil
|
565
557
|
end
|
566
558
|
end
|
567
559
|
if RUBY_PLATFORM =~ /linux/
|
@@ -21,6 +21,8 @@
|
|
21
21
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
22
|
# THE SOFTWARE.
|
23
23
|
|
24
|
+
require 'tmpdir'
|
25
|
+
|
24
26
|
module PhusionPassenger
|
25
27
|
|
26
28
|
# This module autodetects various platform-specific information, and
|
@@ -263,15 +265,12 @@ public
|
|
263
265
|
else
|
264
266
|
raise ArgumentError,"Unsupported language '#{language}'"
|
265
267
|
end
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
268
|
+
Dir.mktmpdir("passenger.", tmpexedir) do |dir|
|
269
|
+
filename = File.join(dir, "check.c")
|
270
|
+
File.open(filename, "w") do |f|
|
271
|
+
f.puts(source)
|
272
|
+
end
|
271
273
|
return system("(#{compiler} #{flags} -c '#{filename}' -o '#{filename}.o') >/dev/null 2>/dev/null")
|
272
|
-
ensure
|
273
|
-
File.unlink(filename) rescue nil
|
274
|
-
File.unlink("#{filename}.o") rescue nil
|
275
274
|
end
|
276
275
|
end
|
277
276
|
private_class_method :try_compile
|
@@ -284,15 +283,12 @@ public
|
|
284
283
|
else
|
285
284
|
raise ArgumentError,"Unsupported language '#{language}'"
|
286
285
|
end
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
286
|
+
Dir.mktmpdir("passenger.", tmpexedir) do |dir|
|
287
|
+
filename = File.join(dir, "check.c")
|
288
|
+
File.open(filename, "w") do |f|
|
289
|
+
f.puts(source)
|
290
|
+
end
|
292
291
|
return system("(#{compiler} #{flags} '#{filename}' -o '#{filename}.out') >/dev/null 2>/dev/null")
|
293
|
-
ensure
|
294
|
-
File.unlink(filename) rescue nil
|
295
|
-
File.unlink("#{filename}.out") rescue nil
|
296
292
|
end
|
297
293
|
end
|
298
294
|
private_class_method :try_link
|
@@ -305,17 +301,16 @@ public
|
|
305
301
|
else
|
306
302
|
raise ArgumentError,"Unsupported language '#{language}'"
|
307
303
|
end
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
304
|
+
Dir.mktmpdir("passenger.", tmpexedir) do |dir|
|
305
|
+
filename = File.join(dir, "check.c")
|
306
|
+
File.open(filename, "w") do |f|
|
307
|
+
f.puts(source)
|
308
|
+
end
|
313
309
|
if system("(#{compiler} #{flags} '#{filename}' -o '#{filename}.out') >/dev/null 2>/dev/null")
|
314
310
|
if Process.respond_to?(:spawn)
|
315
311
|
pid = Process.spawn("#{filename}.out",
|
316
312
|
:out => ["/dev/null", "w"],
|
317
313
|
:err => ["/dev/null", "w"])
|
318
|
-
|
319
314
|
else
|
320
315
|
pid = fork do
|
321
316
|
STDOUT.reopen("/dev/null", "w")
|
@@ -328,9 +323,6 @@ public
|
|
328
323
|
else
|
329
324
|
return false
|
330
325
|
end
|
331
|
-
ensure
|
332
|
-
File.unlink(filename) rescue nil
|
333
|
-
File.unlink("#{filename}.out") rescue nil
|
334
326
|
end
|
335
327
|
end
|
336
328
|
private_class_method :try_compile_and_run
|
@@ -285,16 +285,7 @@ module PlatformInfo
|
|
285
285
|
# headers are placed into the same directory as the Apache headers,
|
286
286
|
# and so 'apr-config' and 'apu-config' won't be necessary in that case.
|
287
287
|
def self.apr_config_needed_for_building_apache_modules?
|
288
|
-
|
289
|
-
File.open(filename, "w") do |f|
|
290
|
-
f.puts("#include <apr.h>")
|
291
|
-
end
|
292
|
-
begin
|
293
|
-
return !system("(gcc #{apache2_module_cflags(false)} -c '#{filename}' -o '#{filename}.o') >/dev/null 2>/dev/null")
|
294
|
-
ensure
|
295
|
-
File.unlink(filename) rescue nil
|
296
|
-
File.unlink("#{filename}.o") rescue nil
|
297
|
-
end
|
288
|
+
return !try_compile(:c, "#include <apr.h>", apache2_module_cflags(false))
|
298
289
|
end
|
299
290
|
memoize :apr_config_needed_for_building_apache_modules?
|
300
291
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Phusion Passenger -
|
1
|
+
# Phusion Passenger - https://www.phusionpassenger.com/
|
2
2
|
# Copyright (c) 2010 Phusion
|
3
3
|
#
|
4
4
|
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
@@ -48,29 +48,54 @@ module PlatformInfo
|
|
48
48
|
def self.ruby_command
|
49
49
|
if in_rvm?
|
50
50
|
name = rvm_ruby_string
|
51
|
-
|
52
|
-
if name &&
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
f
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
51
|
+
dirs = rvm_paths
|
52
|
+
if name && dirs
|
53
|
+
dirs.each do |dir|
|
54
|
+
filename = "#{dir}/wrappers/#{name}/ruby"
|
55
|
+
if File.exist?(filename)
|
56
|
+
contents = File.open(filename, 'rb') do |f|
|
57
|
+
f.read
|
58
|
+
end
|
59
|
+
# Old wrapper scripts reference $HOME which causes
|
60
|
+
# things to blow up when run by a different user.
|
61
|
+
if contents.include?("$HOME")
|
62
|
+
filename = nil
|
63
|
+
end
|
64
|
+
else
|
61
65
|
filename = nil
|
62
66
|
end
|
63
|
-
|
64
|
-
|
67
|
+
if filename
|
68
|
+
return filename
|
69
|
+
end
|
65
70
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
71
|
+
|
72
|
+
# Correctness of these commands are confirmed by mpapis.
|
73
|
+
# If we ever encounter a case for which this logic is not sufficient,
|
74
|
+
# try mpapis' pseudo code:
|
75
|
+
#
|
76
|
+
# rvm_update_prefix = write_to rvm_path ? "" : "rvmsudo"
|
77
|
+
# rvm_gemhome_prefix = write_to GEM_HOME ? "" : "rvmsudo"
|
78
|
+
# repair_command = "#{rvm_update_prefix} rvm get stable && rvm reload && #{rvm_gemhome_prefix} rvm repair all"
|
79
|
+
# wrapper_command = "#{rvm_gemhome_prefix} rvm wrapper #{rvm_ruby_string} --no-prefix --all"
|
80
|
+
case rvm_installation_mode
|
81
|
+
when :single
|
82
|
+
repair_command = "rvm get stable && rvm reload && rvm repair all"
|
83
|
+
wrapper_command = "rvm wrapper #{rvm_ruby_string} --no-prefix --all"
|
84
|
+
when :multi
|
85
|
+
repair_command = "rvmsudo rvm get stable && rvm reload && rvmsudo rvm repair all"
|
86
|
+
wrapper_command = "rvmsudo rvm wrapper #{rvm_ruby_string} --no-prefix --all"
|
87
|
+
when :mixed
|
88
|
+
repair_command = "rvmsudo rvm get stable && rvm reload && rvm repair all"
|
89
|
+
wrapper_command = "rvm wrapper #{rvm_ruby_string} --no-prefix --all"
|
73
90
|
end
|
91
|
+
|
92
|
+
STDERR.puts "Your RVM wrapper scripts are too old, or some " +
|
93
|
+
"wrapper scripts are missing. Please update/regenerate " +
|
94
|
+
"them first by running:\n\n" +
|
95
|
+
" #{repair_command}\n\n" +
|
96
|
+
"If that doesn't seem to work, please run:\n\n" +
|
97
|
+
" #{wrapper_command}"
|
98
|
+
exit 1
|
74
99
|
else
|
75
100
|
# Something's wrong with the user's RVM installation.
|
76
101
|
# Raise an error so that the user knows this instead of
|
@@ -105,7 +130,7 @@ module PlatformInfo
|
|
105
130
|
RUBY_ENGINE != "macruby" &&
|
106
131
|
rb_config['target_os'] !~ /mswin|windows|mingw/
|
107
132
|
end
|
108
|
-
|
133
|
+
|
109
134
|
# Returns the correct 'gem' command for this Ruby interpreter.
|
110
135
|
def self.gem_command
|
111
136
|
return locate_ruby_tool('gem')
|
@@ -156,29 +181,39 @@ module PlatformInfo
|
|
156
181
|
return bindir.include?('/.rvm/') || bindir.include?('/rvm/')
|
157
182
|
end
|
158
183
|
|
159
|
-
# If the current Ruby interpreter is managed by RVM, returns
|
160
|
-
#
|
161
|
-
#
|
162
|
-
|
184
|
+
# If the current Ruby interpreter is managed by RVM, returns all
|
185
|
+
# directories in which RVM places its working files. This is usually
|
186
|
+
# ~/.rvm or /usr/local/rvm, but in mixed-mode installations there
|
187
|
+
# can be multiple such paths.
|
188
|
+
#
|
189
|
+
# Otherwise returns nil.
|
190
|
+
def self.rvm_paths
|
163
191
|
if in_rvm?
|
192
|
+
result = []
|
164
193
|
[ENV['rvm_path'], "~/.rvm", "/usr/local/rvm"].each do |path|
|
165
194
|
next if path.nil?
|
166
195
|
path = File.expand_path(path)
|
167
|
-
|
168
|
-
|
196
|
+
rubies_path = File.join(path, 'rubies')
|
197
|
+
if File.directory?(path) && File.directory?(rubies_path)
|
198
|
+
result << path
|
199
|
+
end
|
200
|
+
end
|
201
|
+
if result.empty?
|
202
|
+
# Failure to locate the RVM path is probably caused by the
|
203
|
+
# user customizing $rvm_path. Older RVM versions don't
|
204
|
+
# export $rvm_path, making us unable to detect its value.
|
205
|
+
STDERR.puts "Unable to locate the RVM path. Your RVM installation " +
|
206
|
+
"is probably too old. Please update it with " +
|
207
|
+
"'rvm get head && rvm reload && rvm repair all'."
|
208
|
+
exit 1
|
209
|
+
else
|
210
|
+
return result
|
169
211
|
end
|
170
|
-
# Failure to locate the RVM path is probably caused by the
|
171
|
-
# user customizing $rvm_path. Older RVM versions don't
|
172
|
-
# export $rvm_path, making us unable to detect its value.
|
173
|
-
STDERR.puts "Unable to locate the RVM path. Your RVM installation " +
|
174
|
-
"is probably too old. Please update it with " +
|
175
|
-
"'rvm get head && rvm reload && rvm repair all'."
|
176
|
-
exit 1
|
177
212
|
else
|
178
213
|
return nil
|
179
214
|
end
|
180
215
|
end
|
181
|
-
memoize :
|
216
|
+
memoize :rvm_paths
|
182
217
|
|
183
218
|
# If the current Ruby interpreter is managed by RVM, returns the
|
184
219
|
# RVM name which identifies the current Ruby interpreter plus the
|
@@ -200,8 +235,12 @@ module PlatformInfo
|
|
200
235
|
# try various strategies...
|
201
236
|
|
202
237
|
# $GEM_HOME usually contains the gem set name.
|
203
|
-
|
204
|
-
|
238
|
+
# It may be something like:
|
239
|
+
# /Users/hongli/.rvm/gems/ruby-1.9.3-p392
|
240
|
+
# But also:
|
241
|
+
# /home/bitnami/.rvm/gems/ruby-1.9.3-p385-perf@njist325/ruby/1.9.1
|
242
|
+
if GEM_HOME && GEM_HOME =~ %r{rvm/gems/(.+)}
|
243
|
+
return $1.sub(/\/.*/, '')
|
205
244
|
end
|
206
245
|
|
207
246
|
# User somehow managed to nuke $GEM_HOME. Extract info
|
@@ -227,6 +266,27 @@ module PlatformInfo
|
|
227
266
|
return nil
|
228
267
|
end
|
229
268
|
memoize :rvm_ruby_string
|
269
|
+
|
270
|
+
# Returns the RVM installation mode:
|
271
|
+
# :single - RVM is installed in single-user mode.
|
272
|
+
# :multi - RVM is installed in multi-user mode.
|
273
|
+
# :mixed - RVM is in a mixed-mode installation.
|
274
|
+
# nil - The current Ruby interpreter is not using RVM.
|
275
|
+
def self.rvm_installation_mode
|
276
|
+
if in_rvm?
|
277
|
+
if ENV['rvm_path'] =~ /\.rvm/
|
278
|
+
return :single
|
279
|
+
else
|
280
|
+
if GEM_HOME =~ /\.rvm/
|
281
|
+
return :mixed
|
282
|
+
else
|
283
|
+
return :multi
|
284
|
+
end
|
285
|
+
end
|
286
|
+
else
|
287
|
+
return nil
|
288
|
+
end
|
289
|
+
end
|
230
290
|
|
231
291
|
# Returns either 'sudo' or 'rvmsudo' depending on whether the current
|
232
292
|
# Ruby interpreter is managed by RVM.
|
@@ -93,7 +93,21 @@ protected
|
|
93
93
|
env[RACK_URL_SCHEME] = HTTP
|
94
94
|
end
|
95
95
|
|
96
|
-
|
96
|
+
begin
|
97
|
+
status, headers, body = @app.call(env)
|
98
|
+
rescue => e
|
99
|
+
socket_wrapper = output
|
100
|
+
if socket_wrapper.source_of_exception?(e)
|
101
|
+
# Handled by AbstractRequestHandler
|
102
|
+
raise e
|
103
|
+
else
|
104
|
+
# It's a good idea to catch application exceptions here because
|
105
|
+
# otherwise maliciously crafted responses can crash the app,
|
106
|
+
# forcing it to be respawned, and thereby effectively DoSing it.
|
107
|
+
print_exception("Rack application object", e)
|
108
|
+
raise AbstractRequestHandler::IgnoreException.new
|
109
|
+
end
|
110
|
+
end
|
97
111
|
begin
|
98
112
|
if full_http_response
|
99
113
|
output.write("HTTP/1.1 #{status.to_i.to_s} Whatever#{CRLF}")
|
@@ -139,6 +153,11 @@ protected
|
|
139
153
|
rewindable_input.close
|
140
154
|
end
|
141
155
|
end
|
156
|
+
|
157
|
+
private
|
158
|
+
def should_swallow_app_error?(e, socket_wrapper)
|
159
|
+
return socket_wrapper && socket_wrapper.source_of_exception?(e) && e.is_a?(Errno::EPIPE)
|
160
|
+
end
|
142
161
|
end
|
143
162
|
|
144
163
|
end # module Rack
|