passenger 5.0.0.beta3 → 5.0.0.rc1
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/.editorconfig +11 -5
- data/CHANGELOG +38 -0
- data/CONTRIBUTING.md +1 -4
- data/Gemfile +0 -1
- data/Gemfile.lock +0 -2
- data/Rakefile +33 -33
- data/bin/passenger +1 -1
- data/bin/passenger-config +1 -1
- data/bin/passenger-install-apache2-module +800 -800
- data/bin/passenger-install-nginx-module +592 -592
- data/bin/passenger-memory-stats +127 -127
- data/bin/passenger-status +216 -216
- data/build/agents.rb +127 -127
- data/build/apache2.rb +87 -87
- data/build/basics.rb +60 -60
- data/build/common_library.rb +165 -165
- data/build/cplusplus_support.rb +51 -51
- data/build/cxx_tests.rb +268 -268
- data/build/debian.rb +143 -143
- data/build/documentation.rb +58 -58
- data/build/integration_tests.rb +81 -81
- data/build/misc.rb +132 -132
- data/build/nginx.rb +20 -20
- data/build/node_tests.rb +7 -7
- data/build/oxt_tests.rb +14 -14
- data/build/packaging.rb +570 -570
- data/build/preprocessor.rb +260 -260
- data/build/rake_extensions.rb +71 -71
- data/build/ruby_extension.rb +29 -29
- data/build/ruby_tests.rb +6 -6
- data/build/test_basics.rb +37 -37
- data/debian.template/control.template +3 -5
- data/dev/copy_boost_headers +134 -134
- data/dev/install_scripts_bootstrap_code.rb +25 -25
- data/dev/list_tests +20 -20
- data/dev/ruby_server.rb +223 -223
- data/dev/runner +18 -18
- data/doc/ServerOptimizationGuide.txt.md +55 -2
- data/doc/Users guide Nginx.txt +0 -26
- data/doc/Users guide Standalone.txt +5 -1
- data/doc/users_guide_snippets/tips.txt +9 -0
- data/ext/common/ApplicationPool2/Group.h +23 -11
- data/ext/common/ApplicationPool2/Implementation.cpp +32 -7
- data/ext/common/ApplicationPool2/Pool.h +22 -17
- data/ext/common/ApplicationPool2/SmartSpawner.h +4 -1
- data/ext/common/ApplicationPool2/Spawner.h +1 -1
- data/ext/common/Constants.h +1 -1
- data/ext/common/agents/Base.cpp +35 -20
- data/ext/common/agents/HelperAgent/Main.cpp +8 -1
- data/ext/common/agents/HelperAgent/OptionParser.h +18 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +2 -83
- data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +54 -1
- data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +7 -4
- data/ext/common/agents/Main.cpp +1 -1
- data/ext/common/agents/Watchdog/Main.cpp +54 -19
- data/ext/nginx/Configuration.c +7 -0
- data/ext/nginx/ContentHandler.c +9 -1
- data/helper-scripts/backtrace-sanitizer.rb +106 -87
- data/helper-scripts/crash-watch.rb +32 -0
- data/helper-scripts/download_binaries/extconf.rb +38 -38
- data/helper-scripts/meteor-loader.rb +107 -107
- data/helper-scripts/prespawn +101 -101
- data/helper-scripts/rack-loader.rb +96 -96
- data/helper-scripts/rack-preloader.rb +137 -137
- data/lib/phusion_passenger.rb +292 -292
- data/lib/phusion_passenger/abstract_installer.rb +438 -438
- data/lib/phusion_passenger/active_support3_extensions/init.rb +168 -170
- data/lib/phusion_passenger/admin_tools.rb +20 -20
- data/lib/phusion_passenger/admin_tools/instance.rb +178 -178
- data/lib/phusion_passenger/admin_tools/instance_registry.rb +61 -61
- data/lib/phusion_passenger/admin_tools/memory_stats.rb +267 -267
- data/lib/phusion_passenger/apache2/config_options.rb +182 -182
- data/lib/phusion_passenger/common_library.rb +479 -485
- data/lib/phusion_passenger/config/about_command.rb +161 -161
- data/lib/phusion_passenger/config/admin_command_command.rb +129 -129
- data/lib/phusion_passenger/config/agent_compiler.rb +121 -121
- data/lib/phusion_passenger/config/build_native_support_command.rb +43 -43
- data/lib/phusion_passenger/config/command.rb +25 -25
- data/lib/phusion_passenger/config/compile_agent_command.rb +62 -62
- data/lib/phusion_passenger/config/compile_nginx_engine_command.rb +88 -73
- data/lib/phusion_passenger/config/detach_process_command.rb +72 -72
- data/lib/phusion_passenger/config/download_agent_command.rb +246 -227
- data/lib/phusion_passenger/config/download_nginx_engine_command.rb +245 -224
- data/lib/phusion_passenger/config/install_agent_command.rb +144 -132
- data/lib/phusion_passenger/config/install_standalone_runtime_command.rb +205 -185
- data/lib/phusion_passenger/config/installation_utils.rb +204 -204
- data/lib/phusion_passenger/config/list_instances_command.rb +64 -64
- data/lib/phusion_passenger/config/main.rb +152 -152
- data/lib/phusion_passenger/config/nginx_engine_compiler.rb +319 -300
- data/lib/phusion_passenger/config/reopen_logs_command.rb +67 -67
- data/lib/phusion_passenger/config/restart_app_command.rb +155 -155
- data/lib/phusion_passenger/config/system_metrics_command.rb +13 -13
- data/lib/phusion_passenger/config/utils.rb +95 -95
- data/lib/phusion_passenger/config/validate_install_command.rb +198 -198
- data/lib/phusion_passenger/console_text_template.rb +25 -25
- data/lib/phusion_passenger/constants.rb +90 -90
- data/lib/phusion_passenger/debug_logging.rb +106 -106
- data/lib/phusion_passenger/loader_shared_helpers.rb +447 -432
- data/lib/phusion_passenger/message_channel.rb +312 -312
- data/lib/phusion_passenger/message_client.rb +176 -176
- data/lib/phusion_passenger/native_support.rb +369 -369
- data/lib/phusion_passenger/nginx/config_options.rb +297 -297
- data/lib/phusion_passenger/packaging.rb +131 -131
- data/lib/phusion_passenger/platform_info.rb +360 -360
- data/lib/phusion_passenger/platform_info/apache.rb +767 -767
- data/lib/phusion_passenger/platform_info/apache_detector.rb +199 -199
- data/lib/phusion_passenger/platform_info/binary_compatibility.rb +107 -107
- data/lib/phusion_passenger/platform_info/compiler.rb +570 -570
- data/lib/phusion_passenger/platform_info/curl.rb +32 -32
- data/lib/phusion_passenger/platform_info/cxx_portability.rb +188 -188
- data/lib/phusion_passenger/platform_info/depcheck.rb +372 -372
- data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +109 -109
- data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
- data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +10 -34
- data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +101 -101
- data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -5
- data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +13 -13
- data/lib/phusion_passenger/platform_info/linux.rb +55 -55
- data/lib/phusion_passenger/platform_info/operating_system.rb +149 -149
- data/lib/phusion_passenger/platform_info/ruby.rb +468 -448
- data/lib/phusion_passenger/platform_info/zlib.rb +9 -9
- data/lib/phusion_passenger/plugin.rb +66 -66
- data/lib/phusion_passenger/preloader_shared_helpers.rb +126 -126
- data/lib/phusion_passenger/public_api.rb +191 -191
- data/lib/phusion_passenger/rack/out_of_band_gc.rb +93 -94
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +231 -227
- data/lib/phusion_passenger/request_handler.rb +567 -577
- data/lib/phusion_passenger/request_handler/thread_handler.rb +379 -381
- data/lib/phusion_passenger/ruby_core_enhancements.rb +86 -86
- data/lib/phusion_passenger/ruby_core_io_enhancements.rb +74 -74
- data/lib/phusion_passenger/simple_benchmarking.rb +25 -25
- data/lib/phusion_passenger/standalone/app_finder.rb +153 -150
- data/lib/phusion_passenger/standalone/command.rb +44 -40
- data/lib/phusion_passenger/standalone/config_utils.rb +53 -53
- data/lib/phusion_passenger/standalone/control_utils.rb +38 -59
- data/lib/phusion_passenger/standalone/main.rb +73 -73
- data/lib/phusion_passenger/standalone/start_command.rb +697 -685
- data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +193 -155
- data/lib/phusion_passenger/standalone/start_command/nginx_engine.rb +162 -133
- data/lib/phusion_passenger/standalone/status_command.rb +64 -64
- data/lib/phusion_passenger/standalone/stop_command.rb +72 -72
- data/lib/phusion_passenger/standalone/version_command.rb +9 -9
- data/lib/phusion_passenger/union_station/connection.rb +32 -32
- data/lib/phusion_passenger/union_station/core.rb +251 -251
- data/lib/phusion_passenger/union_station/transaction.rb +126 -126
- data/lib/phusion_passenger/utils.rb +199 -167
- data/lib/phusion_passenger/utils/ansi_colors.rb +128 -128
- data/lib/phusion_passenger/utils/download.rb +196 -196
- data/lib/phusion_passenger/utils/file_system_watcher.rb +158 -158
- data/lib/phusion_passenger/utils/hosts_file_parser.rb +101 -101
- data/lib/phusion_passenger/utils/lock.rb +31 -31
- data/lib/phusion_passenger/utils/native_support_utils.rb +31 -31
- data/lib/phusion_passenger/utils/progress_bar.rb +26 -26
- data/lib/phusion_passenger/utils/shellwords.rb +20 -20
- data/lib/phusion_passenger/utils/terminal_choice_menu.rb +206 -206
- data/lib/phusion_passenger/utils/unseekable_socket.rb +272 -272
- data/lib/phusion_passenger/vendor/crash_watch/app.rb +129 -0
- data/lib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +341 -0
- data/lib/phusion_passenger/vendor/crash_watch/version.rb +24 -0
- data/lib/phusion_passenger/vendor/daemon_controller.rb +877 -0
- data/lib/phusion_passenger/vendor/daemon_controller/lock_file.rb +127 -0
- data/lib/phusion_passenger/vendor/daemon_controller/spawn.rb +26 -0
- data/lib/phusion_passenger/vendor/daemon_controller/version.rb +29 -0
- data/packaging/rpm/passenger_spec/passenger.spec.template +0 -1
- data/passenger.gemspec +0 -1
- data/resources/templates/config/nginx_engine_compiler/possible_solutions_for_download_and_extraction_problems.txt.erb +27 -0
- data/resources/templates/standalone/config.erb +19 -15
- data/test/integration_tests/apache2_tests.rb +566 -566
- data/test/integration_tests/downloaded_binaries_tests.rb +126 -125
- data/test/integration_tests/native_packaging_spec.rb +296 -296
- data/test/integration_tests/nginx_tests.rb +393 -393
- data/test/integration_tests/shared/example_webapp_tests.rb +282 -280
- data/test/integration_tests/source_packaging_test.rb +138 -138
- data/test/integration_tests/spec_helper.rb +5 -5
- data/test/integration_tests/standalone_tests.rb +367 -367
- data/test/ruby/debug_logging_spec.rb +133 -133
- data/test/ruby/message_channel_spec.rb +186 -186
- data/test/ruby/rack/loader_spec.rb +28 -28
- data/test/ruby/rack/preloader_spec.rb +34 -34
- data/test/ruby/rails3.0/loader_spec.rb +12 -12
- data/test/ruby/rails3.0/preloader_spec.rb +18 -18
- data/test/ruby/rails3.1/loader_spec.rb +12 -12
- data/test/ruby/rails3.1/preloader_spec.rb +18 -18
- data/test/ruby/rails3.2/loader_spec.rb +12 -12
- data/test/ruby/rails3.2/preloader_spec.rb +18 -18
- data/test/ruby/rails4.0/loader_spec.rb +12 -12
- data/test/ruby/rails4.0/preloader_spec.rb +18 -18
- data/test/ruby/rails4.1/loader_spec.rb +12 -12
- data/test/ruby/rails4.1/preloader_spec.rb +18 -18
- data/test/ruby/request_handler_spec.rb +730 -730
- data/test/ruby/shared/loader_sharedspec.rb +224 -224
- data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +327 -327
- data/test/ruby/shared/ruby_loader_sharedspec.rb +47 -47
- data/test/ruby/spec_helper.rb +65 -65
- data/test/ruby/standalone/runtime_installer_spec.rb +384 -384
- data/test/ruby/union_station_spec.rb +276 -276
- data/test/ruby/utils/file_system_watcher_spec.rb +220 -220
- data/test/ruby/utils/hosts_file_parser.rb +248 -248
- data/test/ruby/utils/tee_input_spec.rb +215 -215
- data/test/ruby/utils/unseekable_socket_spec.rb +57 -57
- data/test/ruby/utils_spec.rb +21 -21
- data/test/stub/rack/config.ru +87 -87
- data/test/stub/rack/library.rb +8 -8
- data/test/stub/rack/start.rb +30 -30
- data/test/support/apache2_controller.rb +191 -191
- data/test/support/nginx_controller.rb +90 -99
- data/test/support/placebo-preloader.rb +57 -57
- data/test/support/test_helper.rb +435 -435
- metadata +11 -21
- metadata.gz.asc +7 -7
- data/lib/phusion_passenger/standalone/command2.rb +0 -292
- data/lib/phusion_passenger/standalone/start2_command.rb +0 -799
- data/resources/templates/standalone/download_tool_missing.txt.erb +0 -18
- data/resources/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -17
- data/resources/templates/standalone/run_installer_as_root.txt.erb +0 -8
@@ -29,385 +29,383 @@ PhusionPassenger.require_passenger_lib 'utils/native_support_utils'
|
|
29
29
|
PhusionPassenger.require_passenger_lib 'utils/unseekable_socket'
|
30
30
|
|
31
31
|
module PhusionPassenger
|
32
|
-
class RequestHandler
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
#
|
291
|
-
#
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
end # class RequestHandler
|
32
|
+
class RequestHandler
|
33
|
+
|
34
|
+
# This class encapsulates the logic of a single RequestHandler thread.
|
35
|
+
class ThreadHandler
|
36
|
+
include DebugLogging
|
37
|
+
include Utils
|
38
|
+
|
39
|
+
class Interrupted < StandardError
|
40
|
+
end
|
41
|
+
|
42
|
+
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
|
43
|
+
GET = 'GET'.freeze
|
44
|
+
PING = 'PING'.freeze
|
45
|
+
OOBW = 'OOBW'.freeze
|
46
|
+
PASSENGER_CONNECT_PASSWORD = 'PASSENGER_CONNECT_PASSWORD'.freeze
|
47
|
+
CONTENT_LENGTH = 'CONTENT_LENGTH'.freeze
|
48
|
+
TRANSFER_ENCODING = 'TRANSFER_ENCODING'.freeze
|
49
|
+
|
50
|
+
MAX_HEADER_SIZE = 128 * 1024
|
51
|
+
|
52
|
+
OBJECT_SPACE_SUPPORTS_LIVE_OBJECTS = ObjectSpace.respond_to?(:live_objects)
|
53
|
+
OBJECT_SPACE_SUPPORTS_ALLOCATED_OBJECTS = ObjectSpace.respond_to?(:allocated_objects)
|
54
|
+
OBJECT_SPACE_SUPPORTS_COUNT_OBJECTS = ObjectSpace.respond_to?(:count_objects)
|
55
|
+
GC_SUPPORTS_TIME = GC.respond_to?(:time)
|
56
|
+
GC_SUPPORTS_CLEAR_STATS = GC.respond_to?(:clear_stats)
|
57
|
+
|
58
|
+
attr_reader :thread
|
59
|
+
attr_reader :stats_mutex
|
60
|
+
attr_reader :interruptable
|
61
|
+
attr_reader :iteration
|
62
|
+
|
63
|
+
def initialize(request_handler, options = {})
|
64
|
+
@request_handler = request_handler
|
65
|
+
@server_socket = Utils.require_option(options, :server_socket)
|
66
|
+
@socket_name = Utils.require_option(options, :socket_name)
|
67
|
+
@protocol = Utils.require_option(options, :protocol)
|
68
|
+
@app_group_name = Utils.require_option(options, :app_group_name)
|
69
|
+
Utils.install_options_as_ivars(self, options,
|
70
|
+
:app,
|
71
|
+
:union_station_core,
|
72
|
+
:connect_password,
|
73
|
+
:keepalive_enabled
|
74
|
+
)
|
75
|
+
|
76
|
+
@stats_mutex = Mutex.new
|
77
|
+
@interruptable = false
|
78
|
+
@iteration = 0
|
79
|
+
|
80
|
+
if @protocol == :session
|
81
|
+
metaclass = class << self; self; end
|
82
|
+
metaclass.class_eval do
|
83
|
+
alias parse_request parse_session_request
|
84
|
+
end
|
85
|
+
elsif @protocol == :http
|
86
|
+
metaclass = class << self; self; end
|
87
|
+
metaclass.class_eval do
|
88
|
+
alias parse_request parse_http_request
|
89
|
+
end
|
90
|
+
else
|
91
|
+
raise ArgumentError, "Unknown protocol specified"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def install
|
96
|
+
@thread = Thread.current
|
97
|
+
Thread.current[:passenger_thread_handler] = self
|
98
|
+
PhusionPassenger.call_event(:starting_request_handler_thread)
|
99
|
+
end
|
100
|
+
|
101
|
+
def main_loop(finish_callback)
|
102
|
+
socket_wrapper = Utils::UnseekableSocket.new
|
103
|
+
channel = MessageChannel.new
|
104
|
+
buffer = ''
|
105
|
+
buffer.force_encoding('binary') if buffer.respond_to?(:force_encoding)
|
106
|
+
|
107
|
+
begin
|
108
|
+
finish_callback.call
|
109
|
+
while true
|
110
|
+
hijacked = accept_and_process_next_request(socket_wrapper, channel, buffer)
|
111
|
+
socket_wrapper = Utils::UnseekableSocket.new if hijacked
|
112
|
+
end
|
113
|
+
rescue Interrupted
|
114
|
+
# Do nothing.
|
115
|
+
end
|
116
|
+
debug("Thread handler main loop exited normally")
|
117
|
+
ensure
|
118
|
+
@stats_mutex.synchronize { @interruptable = true }
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
# Returns true if the socket has been hijacked, false otherwise.
|
123
|
+
def accept_and_process_next_request(socket_wrapper, channel, buffer)
|
124
|
+
@stats_mutex.synchronize do
|
125
|
+
@interruptable = true
|
126
|
+
end
|
127
|
+
if @last_connection
|
128
|
+
connection = @last_connection
|
129
|
+
channel.io = connection
|
130
|
+
@last_connection = nil
|
131
|
+
headers = parse_request(connection, channel, buffer)
|
132
|
+
else
|
133
|
+
connection = socket_wrapper.wrap(@server_socket.accept)
|
134
|
+
end
|
135
|
+
@stats_mutex.synchronize do
|
136
|
+
@interruptable = false
|
137
|
+
@iteration += 1
|
138
|
+
end
|
139
|
+
trace(3, "Accepted new request on socket #{@socket_name}")
|
140
|
+
if !headers
|
141
|
+
# New socket accepted, instead of keeping-alive an old one
|
142
|
+
channel.io = connection
|
143
|
+
headers = parse_request(connection, channel, buffer)
|
144
|
+
end
|
145
|
+
if headers
|
146
|
+
prepare_request(connection, headers)
|
147
|
+
begin
|
148
|
+
if headers[REQUEST_METHOD] == GET
|
149
|
+
process_request(headers, connection, socket_wrapper, @protocol == :http)
|
150
|
+
elsif headers[REQUEST_METHOD] == PING
|
151
|
+
process_ping(headers, connection)
|
152
|
+
elsif headers[REQUEST_METHOD] == OOBW
|
153
|
+
process_oobw(headers, connection)
|
154
|
+
else
|
155
|
+
process_request(headers, connection, socket_wrapper, @protocol == :http)
|
156
|
+
end
|
157
|
+
rescue Exception
|
158
|
+
has_error = true
|
159
|
+
raise
|
160
|
+
ensure
|
161
|
+
if headers[RACK_HIJACK_IO]
|
162
|
+
socket_wrapper = nil
|
163
|
+
connection = nil
|
164
|
+
channel = nil
|
165
|
+
end
|
166
|
+
finalize_request(connection, headers, has_error)
|
167
|
+
trace(3, "Request done.")
|
168
|
+
end
|
169
|
+
else
|
170
|
+
trace(2, "No headers parsed; disconnecting client.")
|
171
|
+
end
|
172
|
+
rescue Interrupted
|
173
|
+
raise
|
174
|
+
rescue => e
|
175
|
+
if socket_wrapper && socket_wrapper.source_of_exception?(e)
|
176
|
+
# EPIPE is harmless, it just means that the client closed the connection.
|
177
|
+
# Other errors might indicate a problem so we print them, but they're
|
178
|
+
# probably not bad enough to warrant stopping the request handler.
|
179
|
+
if !e.is_a?(Errno::EPIPE)
|
180
|
+
print_exception("Passenger RequestHandler's client socket", e)
|
181
|
+
end
|
182
|
+
else
|
183
|
+
if headers
|
184
|
+
PhusionPassenger.log_request_exception(headers, e)
|
185
|
+
end
|
186
|
+
raise e if should_reraise_error?(e)
|
187
|
+
end
|
188
|
+
ensure
|
189
|
+
# Close connection if keep-alive not possible
|
190
|
+
if connection && !connection.closed? && !@last_connection
|
191
|
+
# The 'close_write' here prevents forked child
|
192
|
+
# processes from unintentionally keeping the
|
193
|
+
# connection open.
|
194
|
+
begin
|
195
|
+
connection.close_write
|
196
|
+
rescue SystemCallError, IOError
|
197
|
+
end
|
198
|
+
begin
|
199
|
+
connection.close
|
200
|
+
rescue SystemCallError
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def parse_session_request(connection, channel, buffer)
|
206
|
+
headers_data = channel.read_scalar(buffer, MAX_HEADER_SIZE)
|
207
|
+
if headers_data.nil?
|
208
|
+
return
|
209
|
+
end
|
210
|
+
headers = Utils::NativeSupportUtils.split_by_null_into_hash(headers_data)
|
211
|
+
if @connect_password && headers[PASSENGER_CONNECT_PASSWORD] != @connect_password
|
212
|
+
warn "*** Passenger RequestHandler warning: " <<
|
213
|
+
"someone tried to connect with an invalid connect password."
|
214
|
+
return
|
215
|
+
else
|
216
|
+
return headers
|
217
|
+
end
|
218
|
+
rescue SecurityError => e
|
219
|
+
warn("*** Passenger RequestHandler warning: " <<
|
220
|
+
"HTTP header size exceeded maximum.")
|
221
|
+
return
|
222
|
+
end
|
223
|
+
|
224
|
+
# Like parse_session_request, but parses an HTTP request. This is a very minimalistic
|
225
|
+
# HTTP parser and is not intended to be complete, fast or secure, since the HTTP server
|
226
|
+
# socket is intended to be used for debugging purposes only.
|
227
|
+
def parse_http_request(connection, channel, buffer)
|
228
|
+
headers = {}
|
229
|
+
|
230
|
+
data = ""
|
231
|
+
while data !~ /\r\n\r\n/ && data.size < MAX_HEADER_SIZE
|
232
|
+
data << connection.readpartial(16 * 1024)
|
233
|
+
end
|
234
|
+
if data.size >= MAX_HEADER_SIZE
|
235
|
+
warn("*** Passenger RequestHandler warning: " <<
|
236
|
+
"HTTP header size exceeded maximum.")
|
237
|
+
return
|
238
|
+
end
|
239
|
+
|
240
|
+
data.gsub!(/\r\n\r\n.*/, '')
|
241
|
+
data.split("\r\n").each_with_index do |line, i|
|
242
|
+
if i == 0
|
243
|
+
# GET / HTTP/1.1
|
244
|
+
line =~ /^([A-Za-z]+) (.+?) (HTTP\/\d\.\d)$/
|
245
|
+
request_method = $1
|
246
|
+
request_uri = $2
|
247
|
+
protocol = $3
|
248
|
+
path_info, query_string = request_uri.split("?", 2)
|
249
|
+
headers[REQUEST_METHOD] = request_method
|
250
|
+
headers["REQUEST_URI"] = request_uri
|
251
|
+
headers["QUERY_STRING"] = query_string || ""
|
252
|
+
headers["SCRIPT_NAME"] = ""
|
253
|
+
headers["PATH_INFO"] = path_info
|
254
|
+
headers["SERVER_NAME"] = "127.0.0.1"
|
255
|
+
headers["SERVER_PORT"] = connection.addr[1].to_s
|
256
|
+
headers["SERVER_PROTOCOL"] = protocol
|
257
|
+
else
|
258
|
+
header, value = line.split(/\s*:\s*/, 2)
|
259
|
+
header.upcase! # "Foo-Bar" => "FOO-BAR"
|
260
|
+
header.gsub!("-", "_") # => "FOO_BAR"
|
261
|
+
if header == CONTENT_LENGTH || header == "CONTENT_TYPE"
|
262
|
+
headers[header] = value
|
263
|
+
else
|
264
|
+
headers["HTTP_#{header}"] = value
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
if @connect_password && headers["HTTP_X_PASSENGER_CONNECT_PASSWORD"] != @connect_password
|
270
|
+
warn "*** Passenger RequestHandler warning: " <<
|
271
|
+
"someone tried to connect with an invalid connect password."
|
272
|
+
return
|
273
|
+
else
|
274
|
+
return headers
|
275
|
+
end
|
276
|
+
rescue EOFError
|
277
|
+
return
|
278
|
+
end
|
279
|
+
|
280
|
+
def process_ping(env, connection)
|
281
|
+
connection.write("pong")
|
282
|
+
end
|
283
|
+
|
284
|
+
def process_oobw(env, connection)
|
285
|
+
PhusionPassenger.call_event(:oob_work)
|
286
|
+
connection.write("oobw done")
|
287
|
+
end
|
288
|
+
|
289
|
+
# def process_request(env, connection, socket_wrapper, full_http_response)
|
290
|
+
# raise NotImplementedError, "Override with your own implementation!"
|
291
|
+
# end
|
292
|
+
|
293
|
+
def prepare_request(connection, headers)
|
294
|
+
transfer_encoding = headers[TRANSFER_ENCODING]
|
295
|
+
content_length = headers[CONTENT_LENGTH]
|
296
|
+
@can_keepalive = @keepalive_enabled &&
|
297
|
+
!transfer_encoding &&
|
298
|
+
!content_length
|
299
|
+
@keepalive_performed = false
|
300
|
+
|
301
|
+
if !transfer_encoding && !content_length
|
302
|
+
connection.simulate_eof!
|
303
|
+
end
|
304
|
+
|
305
|
+
if @union_station_core && headers[PASSENGER_TXN_ID]
|
306
|
+
txn_id = headers[PASSENGER_TXN_ID]
|
307
|
+
union_station_key = headers[PASSENGER_UNION_STATION_KEY]
|
308
|
+
transaction = @union_station_core.continue_transaction(txn_id,
|
309
|
+
@app_group_name,
|
310
|
+
:requests, union_station_key)
|
311
|
+
headers[UNION_STATION_REQUEST_TRANSACTION] = transaction
|
312
|
+
headers[UNION_STATION_CORE] = @union_station_core
|
313
|
+
headers[PASSENGER_APP_GROUP_NAME] = @app_group_name
|
314
|
+
Thread.current[UNION_STATION_REQUEST_TRANSACTION] = transaction
|
315
|
+
Thread.current[UNION_STATION_CORE] = @union_station_core
|
316
|
+
Thread.current[PASSENGER_TXN_ID] = txn_id
|
317
|
+
Thread.current[PASSENGER_UNION_STATION_KEY] = union_station_key
|
318
|
+
if OBJECT_SPACE_SUPPORTS_LIVE_OBJECTS
|
319
|
+
transaction.message("Initial objects on heap: #{ObjectSpace.live_objects}")
|
320
|
+
end
|
321
|
+
if OBJECT_SPACE_SUPPORTS_ALLOCATED_OBJECTS
|
322
|
+
transaction.message("Initial objects allocated so far: #{ObjectSpace.allocated_objects}")
|
323
|
+
elsif OBJECT_SPACE_SUPPORTS_COUNT_OBJECTS
|
324
|
+
count = ObjectSpace.count_objects
|
325
|
+
transaction.message("Initial objects allocated so far: #{count[:TOTAL] - count[:FREE]}")
|
326
|
+
end
|
327
|
+
if GC_SUPPORTS_TIME
|
328
|
+
transaction.message("Initial GC time: #{GC.time}")
|
329
|
+
end
|
330
|
+
transaction.begin_measure("app request handler processing")
|
331
|
+
end
|
332
|
+
|
333
|
+
#################
|
334
|
+
end
|
335
|
+
|
336
|
+
def finalize_request(connection, headers, has_error)
|
337
|
+
transaction = headers[UNION_STATION_REQUEST_TRANSACTION]
|
338
|
+
Thread.current[UNION_STATION_CORE] = nil
|
339
|
+
Thread.current[UNION_STATION_REQUEST_TRANSACTION] = nil
|
340
|
+
|
341
|
+
if connection
|
342
|
+
connection.stop_simulating_eof!
|
343
|
+
end
|
344
|
+
|
345
|
+
if transaction && !transaction.closed?
|
346
|
+
exception_occurred = false
|
347
|
+
begin
|
348
|
+
transaction.end_measure("app request handler processing", has_error)
|
349
|
+
if OBJECT_SPACE_SUPPORTS_LIVE_OBJECTS
|
350
|
+
transaction.message("Final objects on heap: #{ObjectSpace.live_objects}")
|
351
|
+
end
|
352
|
+
if OBJECT_SPACE_SUPPORTS_ALLOCATED_OBJECTS
|
353
|
+
transaction.message("Final objects allocated so far: #{ObjectSpace.allocated_objects}")
|
354
|
+
elsif OBJECT_SPACE_SUPPORTS_COUNT_OBJECTS
|
355
|
+
count = ObjectSpace.count_objects
|
356
|
+
transaction.message("Final objects allocated so far: #{count[:TOTAL] - count[:FREE]}")
|
357
|
+
end
|
358
|
+
if GC_SUPPORTS_TIME
|
359
|
+
transaction.message("Final GC time: #{GC.time}")
|
360
|
+
end
|
361
|
+
if GC_SUPPORTS_CLEAR_STATS
|
362
|
+
# Clear statistics to void integer wraps.
|
363
|
+
GC.clear_stats
|
364
|
+
end
|
365
|
+
rescue Exception
|
366
|
+
# Maybe this exception was raised while communicating
|
367
|
+
# with the logging agent. If that is the case then
|
368
|
+
# transaction.close may also raise an exception, but we're only
|
369
|
+
# interested in the original exception. So if this
|
370
|
+
# situation occurs we must ignore any exceptions raised
|
371
|
+
# by transaction.close.
|
372
|
+
exception_occurred = true
|
373
|
+
raise
|
374
|
+
ensure
|
375
|
+
# It is important that the following call receives an ACK
|
376
|
+
# from the logging agent and that we don't close the socket
|
377
|
+
# connection until the ACK has been received, otherwise
|
378
|
+
# the helper agent may close the transaction before this
|
379
|
+
# process's openTransaction command is processed.
|
380
|
+
begin
|
381
|
+
transaction.close
|
382
|
+
rescue
|
383
|
+
raise if !exception_occurred
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
if !has_error && @keepalive_performed && connection
|
389
|
+
trace(3, "Keep-aliving connection.")
|
390
|
+
@last_connection = connection
|
391
|
+
end
|
392
|
+
|
393
|
+
#################
|
394
|
+
end
|
395
|
+
|
396
|
+
def should_reraise_error?(e)
|
397
|
+
# Stubable by unit tests.
|
398
|
+
return true
|
399
|
+
end
|
400
|
+
|
401
|
+
def should_reraise_app_error?(e, socket_wrapper)
|
402
|
+
return false
|
403
|
+
end
|
404
|
+
|
405
|
+
def should_swallow_app_error?(e, socket_wrapper)
|
406
|
+
return socket_wrapper && socket_wrapper.source_of_exception?(e) && e.is_a?(Errno::EPIPE)
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
end # class RequestHandler
|
413
411
|
end # module PhusionPassenger
|