passenger 4.0.38 → 4.0.39
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.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/CHANGELOG +24 -0
- data/bin/passenger +5 -0
- data/bin/passenger-install-apache2-module +1 -1
- data/bin/passenger-install-nginx-module +1 -1
- data/build/apache2.rb +2 -6
- data/build/cxx_tests.rb +5 -0
- data/build/packaging.rb +1 -0
- data/dev/list_tests.rb +36 -0
- data/doc/Users guide Standalone.txt +20 -5
- data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +6 -13
- data/ext/common/Constants.h +1 -1
- data/ext/common/MessageClient.h +7 -7
- data/ext/common/Utils.cpp +6 -2
- data/ext/common/Utils/MessageIO.h +6 -11
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +6 -3
- data/ext/common/agents/HelperAgent/RequestHandler.h +146 -24
- data/ext/ruby/extconf.rb +12 -0
- data/ext/ruby/passenger_native_support.c +18 -13
- data/helper-scripts/wsgi-loader.py +25 -2
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/config/about_command.rb +3 -0
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -4
- data/lib/phusion_passenger/request_handler/thread_handler.rb +0 -21
- data/lib/phusion_passenger/standalone/command.rb +10 -3
- data/lib/phusion_passenger/standalone/start_command.rb +4 -0
- data/lib/phusion_passenger/utils/tee_input.rb +82 -14
- data/lib/phusion_passenger/utils/terminal_choice_menu.rb +17 -2
- data/lib/phusion_passenger/utils/unseekable_socket.rb +0 -30
- data/resources/templates/error_layout.html.template +1 -1
- data/resources/templates/standalone/config.erb +18 -5
- data/test/cxx/RequestHandlerTest.cpp +410 -194
- data/test/integration_tests/native_packaging_spec.rb +5 -1
- data/test/ruby/request_handler_spec.rb +4 -71
- data/test/ruby/utils/tee_input_spec.rb +235 -0
- metadata +5 -3
- metadata.gz.asc +7 -7
data/ext/ruby/extconf.rb
CHANGED
@@ -35,7 +35,9 @@ if RUBY_PLATFORM =~ /solaris/
|
|
35
35
|
end
|
36
36
|
|
37
37
|
have_header('alloca.h')
|
38
|
+
have_header('ruby/version.h')
|
38
39
|
have_header('ruby/io.h')
|
40
|
+
have_var('ruby_version')
|
39
41
|
have_func('rb_thread_io_blocking_region')
|
40
42
|
|
41
43
|
with_cflags($CFLAGS) do
|
@@ -48,5 +50,15 @@ with_cflags($CFLAGS) do
|
|
48
50
|
File.open("Makefile", "w") do |f|
|
49
51
|
f.write(makefile)
|
50
52
|
end
|
53
|
+
elsif RUBY_PLATFORM =~ /darwin/
|
54
|
+
# The OS X Clang 503.0.38 update (circa March 15 2014) broke
|
55
|
+
# /usr/bin/ruby's mkmf. mkmf inserts -multiply_definedsuppress
|
56
|
+
# into the Makefile, but that flag is no longer supported by
|
57
|
+
# Clang. We remove this manually.
|
58
|
+
makefile = File.read("Makefile")
|
59
|
+
makefile.sub!(/-multiply_definedsuppress/, "")
|
60
|
+
File.open("Makefile", "w") do |f|
|
61
|
+
f.write(makefile)
|
62
|
+
end
|
51
63
|
end
|
52
64
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2014 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -27,12 +27,15 @@
|
|
27
27
|
/* Ruby 1.9 */
|
28
28
|
#include "ruby/intern.h"
|
29
29
|
#include "ruby/io.h"
|
30
|
-
#include "ruby/version.h"
|
31
30
|
#else
|
31
|
+
/* Ruby 1.8 */
|
32
32
|
#include "rubysig.h"
|
33
33
|
#include "rubyio.h"
|
34
34
|
#include "version.h"
|
35
35
|
#endif
|
36
|
+
#ifdef HAVE_RUBY_VERSION_H
|
37
|
+
#include "ruby/version.h"
|
38
|
+
#endif
|
36
39
|
#include <sys/types.h>
|
37
40
|
#include <sys/stat.h>
|
38
41
|
#include <sys/ioctl.h>
|
@@ -920,17 +923,19 @@ Init_passenger_native_support() {
|
|
920
923
|
#define ESTIMATED_RUBY_MINOR_VERSION '8'
|
921
924
|
#endif
|
922
925
|
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
"
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
926
|
+
#ifdef HAVE_RUBY_VERSION
|
927
|
+
if (strlen(ruby_version) < sizeof("1.8.7") - 1
|
928
|
+
|| ruby_version[0] != '1'
|
929
|
+
|| ruby_version[1] != '.'
|
930
|
+
|| ruby_version[2] != ESTIMATED_RUBY_MINOR_VERSION)
|
931
|
+
{
|
932
|
+
fprintf(stderr, " --> passenger_native_support was compiled for Ruby %s, "
|
933
|
+
"but you're currently running Ruby %s\n",
|
934
|
+
ESTIMATED_RUBY_VERSION, ruby_version);
|
935
|
+
fprintf(stderr, " Refusing to load existing passenger_native_support.\n");
|
936
|
+
return;
|
937
|
+
}
|
938
|
+
#endif
|
934
939
|
#endif
|
935
940
|
|
936
941
|
mPassenger = rb_define_module("PhusionPassenger");
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
2
|
# Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
# Copyright (c) 2010-
|
3
|
+
# Copyright (c) 2010-2014 Phusion
|
4
4
|
#
|
5
5
|
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
#
|
@@ -22,7 +22,7 @@
|
|
22
22
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
23
|
# THE SOFTWARE.
|
24
24
|
|
25
|
-
import sys, os, re, imp, traceback, socket, select, struct, logging, errno
|
25
|
+
import sys, os, re, imp, threading, signal, traceback, socket, select, struct, logging, errno
|
26
26
|
|
27
27
|
options = {}
|
28
28
|
|
@@ -68,6 +68,28 @@ def create_server_socket():
|
|
68
68
|
s.listen(1000)
|
69
69
|
return (filename, s)
|
70
70
|
|
71
|
+
def install_signal_handlers():
|
72
|
+
def debug(sig, frame):
|
73
|
+
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
|
74
|
+
code = []
|
75
|
+
for thread_id, stack in sys._current_frames().items():
|
76
|
+
code.append("\n# Thread: %s(%d)" % (id2name.get(thread_id,""), thread_id))
|
77
|
+
for filename, lineno, name, line in traceback.extract_stack(stack):
|
78
|
+
code.append(' File: "%s", line %d, in %s' % (filename, lineno, name))
|
79
|
+
if line:
|
80
|
+
code.append(" %s" % (line.strip()))
|
81
|
+
print("\n".join(code))
|
82
|
+
|
83
|
+
def debug_and_exit(sig, frame):
|
84
|
+
debug(sig, frame)
|
85
|
+
sys.exit(1)
|
86
|
+
|
87
|
+
# Unfortunately, there's no way to install a signal handler that prints
|
88
|
+
# the backtrace without interrupting the current system call. os.siginterrupt()
|
89
|
+
# doesn't seem to work properly either. That is why we only have a SIGABRT
|
90
|
+
# handler and no SIGQUIT handler.
|
91
|
+
signal.signal(signal.SIGABRT, debug_and_exit)
|
92
|
+
|
71
93
|
def advertise_sockets(socket_filename):
|
72
94
|
print("!> socket: main;unix:%s;session;1" % socket_filename)
|
73
95
|
print("!> ")
|
@@ -270,6 +292,7 @@ if __name__ == "__main__":
|
|
270
292
|
handshake_and_read_startup_request()
|
271
293
|
app_module = load_app()
|
272
294
|
socket_filename, server_socket = create_server_socket()
|
295
|
+
install_signal_handlers()
|
273
296
|
handler = RequestHandler(server_socket, sys.stdin, app_module.application)
|
274
297
|
print("!> Ready")
|
275
298
|
advertise_sockets(socket_filename)
|
data/lib/phusion_passenger.rb
CHANGED
@@ -30,7 +30,7 @@ module PhusionPassenger
|
|
30
30
|
|
31
31
|
PACKAGE_NAME = 'passenger'
|
32
32
|
# Run 'rake ext/common/Constants.h' after changing this number.
|
33
|
-
VERSION_STRING = '4.0.
|
33
|
+
VERSION_STRING = '4.0.39'
|
34
34
|
|
35
35
|
PREFERRED_NGINX_VERSION = '1.4.6'
|
36
36
|
NGINX_SHA256_CHECKSUM = '7a8b5b15d708b5b9c61e723bd93faa247b06c8b90babb76f612c128edb5812c6'
|
@@ -42,6 +42,7 @@ class AboutCommand < Command
|
|
42
42
|
puts " includedir Show the Nginx runtime library headers directory."
|
43
43
|
puts " nginx-addon-dir Show #{PROGRAM_NAME}'s Nginx addon directory."
|
44
44
|
puts " nginx-libs Show Nginx runtime library flags."
|
45
|
+
puts " resourcesdir Show #{PROGRAM_NAME}'s resources directory."
|
45
46
|
puts " compiled Check whether runtime libraries are compiled."
|
46
47
|
puts " natively-packaged Check whether Phusion Passenger is natively"
|
47
48
|
puts " packaged."
|
@@ -77,6 +78,8 @@ class AboutCommand < Command
|
|
77
78
|
puts PhusionPassenger.nginx_module_source_dir
|
78
79
|
when "--nginx-libs"
|
79
80
|
puts "#{common_library.link_objects_as_string} #{PhusionPassenger.lib_dir}/common/libboost_oxt.a"
|
81
|
+
when "--resourcesdir"
|
82
|
+
puts PhusionPassenger.resources_dir
|
80
83
|
when "--compiled"
|
81
84
|
common_library.link_objects.each do |filename|
|
82
85
|
if !File.exist?(filename)
|
@@ -46,7 +46,6 @@ class ThreadHandler
|
|
46
46
|
OOBW = 'OOBW'.freeze
|
47
47
|
PASSENGER_CONNECT_PASSWORD = 'PASSENGER_CONNECT_PASSWORD'.freeze
|
48
48
|
CONTENT_LENGTH = 'CONTENT_LENGTH'.freeze
|
49
|
-
HTTP_TRANSFER_ENCODING = 'HTTP_TRANSFER_ENCODING'.freeze
|
50
49
|
|
51
50
|
MAX_HEADER_SIZE = 128 * 1024
|
52
51
|
|
@@ -277,10 +276,6 @@ private
|
|
277
276
|
# end
|
278
277
|
|
279
278
|
def prepare_request(connection, headers)
|
280
|
-
if !may_have_request_body?(headers)
|
281
|
-
connection.simulate_eof!
|
282
|
-
end
|
283
|
-
|
284
279
|
if @analytics_logger && headers[PASSENGER_TXN_ID]
|
285
280
|
txn_id = headers[PASSENGER_TXN_ID]
|
286
281
|
union_station_key = headers[PASSENGER_UNION_STATION_KEY]
|
@@ -310,10 +305,6 @@ private
|
|
310
305
|
end
|
311
306
|
|
312
307
|
def finalize_request(connection, headers, has_error)
|
313
|
-
if connection
|
314
|
-
connection.stop_simulating_eof!
|
315
|
-
end
|
316
|
-
|
317
308
|
log = headers[PASSENGER_ANALYTICS_WEB_LOG]
|
318
309
|
if log && !log.closed?
|
319
310
|
exception_occurred = false
|
@@ -385,18 +376,6 @@ private
|
|
385
376
|
end
|
386
377
|
end
|
387
378
|
|
388
|
-
def may_have_request_body?(headers)
|
389
|
-
if headers[REQUEST_METHOD] == GET
|
390
|
-
if content_length = headers[CONTENT_LENGTH]
|
391
|
-
return content_length != 0
|
392
|
-
else
|
393
|
-
return headers.has_key?(HTTP_TRANSFER_ENCODING)
|
394
|
-
end
|
395
|
-
else
|
396
|
-
return true
|
397
|
-
end
|
398
|
-
end
|
399
|
-
|
400
379
|
def should_reraise_error?(e)
|
401
380
|
# Stubable by unit tests.
|
402
381
|
return true
|
@@ -217,10 +217,8 @@ private
|
|
217
217
|
|
218
218
|
File.open(@config_filename, 'w') do |f|
|
219
219
|
f.chmod(0644)
|
220
|
-
template_filename = File.join(PhusionPassenger.resources_dir,
|
221
|
-
"templates", "standalone", "config.erb")
|
222
220
|
require_erb
|
223
|
-
erb = ERB.new(File.read(
|
221
|
+
erb = ERB.new(File.read(nginx_config_template_filename))
|
224
222
|
current_user = Etc.getpwuid(Process.uid).name
|
225
223
|
|
226
224
|
# The template requires some helper methods which are defined in start_command.rb.
|
@@ -230,6 +228,15 @@ private
|
|
230
228
|
end
|
231
229
|
end
|
232
230
|
|
231
|
+
def nginx_config_template_filename
|
232
|
+
if @options[:nginx_config_template]
|
233
|
+
return @options[:nginx_config_template]
|
234
|
+
else
|
235
|
+
return File.join(PhusionPassenger.resources_dir,
|
236
|
+
"templates", "standalone", "config.erb")
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
233
240
|
def serialize_strset(*items)
|
234
241
|
if "".respond_to?(:force_encoding)
|
235
242
|
items = items.map { |x| x.force_encoding('binary') }
|
@@ -270,6 +270,10 @@ private
|
|
270
270
|
"be used instead of downloading from the Internet")) do |value|
|
271
271
|
@options[:nginx_tarball] = File.expand_path(value)
|
272
272
|
end
|
273
|
+
opts.on("--nginx-config-template FILENAME", String,
|
274
|
+
wrap_desc("The template to use for generating the Nginx config file")) do |value|
|
275
|
+
@options[:nginx_config_template] = File.expand_path(value)
|
276
|
+
end
|
273
277
|
opts.on("--binaries-url-root URL", String,
|
274
278
|
wrap_desc("If Nginx needs to be installed, then the specified URL will be " +
|
275
279
|
"checked for binaries prior to a local build.")) do |value|
|
@@ -72,6 +72,8 @@ module Utils
|
|
72
72
|
# "rack.input" of the Rack environment.
|
73
73
|
class TeeInput
|
74
74
|
CONTENT_LENGTH = "CONTENT_LENGTH".freeze
|
75
|
+
HTTP_TRANSFER_ENCODING = "HTTP_TRANSFER_ENCODING".freeze
|
76
|
+
CHUNKED = "chunked".freeze
|
75
77
|
|
76
78
|
# The maximum size (in +bytes+) to buffer in memory before
|
77
79
|
# resorting to a temporary file. Default is 112 kilobytes.
|
@@ -92,11 +94,18 @@ class TeeInput
|
|
92
94
|
# Initializes a new TeeInput object. You normally do not have to call
|
93
95
|
# this unless you are writing an HTTP server.
|
94
96
|
def initialize(socket, env)
|
95
|
-
@len = env[CONTENT_LENGTH]
|
96
|
-
|
97
|
+
if @len = env[CONTENT_LENGTH]
|
98
|
+
@len = @len.to_i
|
99
|
+
elsif env[HTTP_TRANSFER_ENCODING] != CHUNKED
|
100
|
+
@len = 0
|
101
|
+
end
|
97
102
|
@socket = socket
|
98
|
-
@
|
99
|
-
|
103
|
+
@bytes_read = 0
|
104
|
+
if @len && @len <= @@client_body_buffer_size
|
105
|
+
@tmp = StringIO.new("")
|
106
|
+
else
|
107
|
+
@tmp = TmpIO.new("PassengerTeeInput")
|
108
|
+
end
|
100
109
|
end
|
101
110
|
|
102
111
|
def close
|
@@ -104,18 +113,37 @@ class TeeInput
|
|
104
113
|
end
|
105
114
|
|
106
115
|
def size
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
116
|
+
if @len
|
117
|
+
@len
|
118
|
+
else
|
119
|
+
pos = @tmp.pos
|
120
|
+
consume!
|
121
|
+
@tmp.pos = pos
|
122
|
+
@len = @tmp.size
|
123
|
+
end
|
112
124
|
end
|
113
125
|
|
114
|
-
def read(
|
115
|
-
|
116
|
-
|
126
|
+
def read(len = nil, buf = "")
|
127
|
+
buf ||= ""
|
128
|
+
if len
|
129
|
+
if len < 0
|
130
|
+
raise ArgumentError, "negative length #{len} given"
|
131
|
+
elsif len == 0
|
132
|
+
buf.replace('')
|
133
|
+
buf
|
134
|
+
else
|
135
|
+
if socket_drained?
|
136
|
+
@tmp.read(len, buf)
|
137
|
+
else
|
138
|
+
tee(read_exact(len, buf))
|
139
|
+
end
|
140
|
+
end
|
117
141
|
else
|
118
|
-
|
142
|
+
if socket_drained?
|
143
|
+
@tmp.read(nil, buf)
|
144
|
+
else
|
145
|
+
tee(read_all(buf))
|
146
|
+
end
|
119
147
|
end
|
120
148
|
end
|
121
149
|
|
@@ -123,7 +151,18 @@ class TeeInput
|
|
123
151
|
if socket_drained?
|
124
152
|
@tmp.gets
|
125
153
|
else
|
126
|
-
|
154
|
+
if @bytes_read == @len
|
155
|
+
nil
|
156
|
+
elsif line = @socket.gets
|
157
|
+
if @len
|
158
|
+
max_len = @len - @bytes_read
|
159
|
+
line.slice!(max_len, line.size - max_len)
|
160
|
+
end
|
161
|
+
@bytes_read += line.size
|
162
|
+
tee(line)
|
163
|
+
else
|
164
|
+
nil
|
165
|
+
end
|
127
166
|
end
|
128
167
|
end
|
129
168
|
|
@@ -160,6 +199,7 @@ private
|
|
160
199
|
def consume!
|
161
200
|
junk = ""
|
162
201
|
nil while read(16 * 1024, junk)
|
202
|
+
@socket = nil
|
163
203
|
end
|
164
204
|
|
165
205
|
def tee(buffer)
|
@@ -168,6 +208,34 @@ private
|
|
168
208
|
end
|
169
209
|
buffer
|
170
210
|
end
|
211
|
+
|
212
|
+
def read_exact(len, buf)
|
213
|
+
if @len
|
214
|
+
max_len = @len - @bytes_read
|
215
|
+
len = max_len if len > max_len
|
216
|
+
return nil if len == 0
|
217
|
+
end
|
218
|
+
ret = @socket.read(len, buf)
|
219
|
+
@bytes_read += ret.size if ret
|
220
|
+
ret
|
221
|
+
end
|
222
|
+
|
223
|
+
def read_all(buf)
|
224
|
+
if @len
|
225
|
+
ret = @socket.read(@len - @bytes_read, buf)
|
226
|
+
if ret
|
227
|
+
@bytes_read += ret.size
|
228
|
+
ret
|
229
|
+
else
|
230
|
+
buf.replace("")
|
231
|
+
buf
|
232
|
+
end
|
233
|
+
else
|
234
|
+
ret = @socket.read(nil, buf)
|
235
|
+
@bytes_read += ret.size
|
236
|
+
ret
|
237
|
+
end
|
238
|
+
end
|
171
239
|
end
|
172
240
|
|
173
241
|
end # module Utils
|
@@ -109,6 +109,9 @@ private
|
|
109
109
|
when " "
|
110
110
|
process_toggle
|
111
111
|
return false
|
112
|
+
when "!"
|
113
|
+
process_disable_utf8
|
114
|
+
return false
|
112
115
|
when "\r"
|
113
116
|
return true
|
114
117
|
else
|
@@ -131,6 +134,10 @@ private
|
|
131
134
|
@choices[@pointer].toggle!
|
132
135
|
end
|
133
136
|
|
137
|
+
def process_disable_utf8
|
138
|
+
ENV['UTF8_MENUS'] = '0'
|
139
|
+
end
|
140
|
+
|
134
141
|
def render_to_string
|
135
142
|
str = ""
|
136
143
|
@choices.each_with_index do |choice, i|
|
@@ -143,11 +150,11 @@ private
|
|
143
150
|
end
|
144
151
|
|
145
152
|
def render_pointer(index)
|
146
|
-
return @pointer == index ? "‣" : " "
|
153
|
+
return @pointer == index ? maybe_utf8("‣", ">") : " "
|
147
154
|
end
|
148
155
|
|
149
156
|
def render_checkbox(checked)
|
150
|
-
return checked ? "⬢" : "⬡"
|
157
|
+
return checked ? maybe_utf8("⬢", "(*)") : maybe_utf8("⬡", "( )")
|
151
158
|
end
|
152
159
|
|
153
160
|
def display(str)
|
@@ -163,6 +170,14 @@ private
|
|
163
170
|
end
|
164
171
|
end
|
165
172
|
|
173
|
+
def maybe_utf8(utf8, plain)
|
174
|
+
if ENV['UTF8_MENUS'] == '0'
|
175
|
+
return plain
|
176
|
+
else
|
177
|
+
return utf8
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
166
181
|
def hide_cursor
|
167
182
|
display("\x1b[?25l")
|
168
183
|
end
|