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.

Files changed (218) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +11 -5
  5. data/CHANGELOG +38 -0
  6. data/CONTRIBUTING.md +1 -4
  7. data/Gemfile +0 -1
  8. data/Gemfile.lock +0 -2
  9. data/Rakefile +33 -33
  10. data/bin/passenger +1 -1
  11. data/bin/passenger-config +1 -1
  12. data/bin/passenger-install-apache2-module +800 -800
  13. data/bin/passenger-install-nginx-module +592 -592
  14. data/bin/passenger-memory-stats +127 -127
  15. data/bin/passenger-status +216 -216
  16. data/build/agents.rb +127 -127
  17. data/build/apache2.rb +87 -87
  18. data/build/basics.rb +60 -60
  19. data/build/common_library.rb +165 -165
  20. data/build/cplusplus_support.rb +51 -51
  21. data/build/cxx_tests.rb +268 -268
  22. data/build/debian.rb +143 -143
  23. data/build/documentation.rb +58 -58
  24. data/build/integration_tests.rb +81 -81
  25. data/build/misc.rb +132 -132
  26. data/build/nginx.rb +20 -20
  27. data/build/node_tests.rb +7 -7
  28. data/build/oxt_tests.rb +14 -14
  29. data/build/packaging.rb +570 -570
  30. data/build/preprocessor.rb +260 -260
  31. data/build/rake_extensions.rb +71 -71
  32. data/build/ruby_extension.rb +29 -29
  33. data/build/ruby_tests.rb +6 -6
  34. data/build/test_basics.rb +37 -37
  35. data/debian.template/control.template +3 -5
  36. data/dev/copy_boost_headers +134 -134
  37. data/dev/install_scripts_bootstrap_code.rb +25 -25
  38. data/dev/list_tests +20 -20
  39. data/dev/ruby_server.rb +223 -223
  40. data/dev/runner +18 -18
  41. data/doc/ServerOptimizationGuide.txt.md +55 -2
  42. data/doc/Users guide Nginx.txt +0 -26
  43. data/doc/Users guide Standalone.txt +5 -1
  44. data/doc/users_guide_snippets/tips.txt +9 -0
  45. data/ext/common/ApplicationPool2/Group.h +23 -11
  46. data/ext/common/ApplicationPool2/Implementation.cpp +32 -7
  47. data/ext/common/ApplicationPool2/Pool.h +22 -17
  48. data/ext/common/ApplicationPool2/SmartSpawner.h +4 -1
  49. data/ext/common/ApplicationPool2/Spawner.h +1 -1
  50. data/ext/common/Constants.h +1 -1
  51. data/ext/common/agents/Base.cpp +35 -20
  52. data/ext/common/agents/HelperAgent/Main.cpp +8 -1
  53. data/ext/common/agents/HelperAgent/OptionParser.h +18 -4
  54. data/ext/common/agents/HelperAgent/RequestHandler.h +2 -83
  55. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +54 -1
  56. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +7 -4
  57. data/ext/common/agents/Main.cpp +1 -1
  58. data/ext/common/agents/Watchdog/Main.cpp +54 -19
  59. data/ext/nginx/Configuration.c +7 -0
  60. data/ext/nginx/ContentHandler.c +9 -1
  61. data/helper-scripts/backtrace-sanitizer.rb +106 -87
  62. data/helper-scripts/crash-watch.rb +32 -0
  63. data/helper-scripts/download_binaries/extconf.rb +38 -38
  64. data/helper-scripts/meteor-loader.rb +107 -107
  65. data/helper-scripts/prespawn +101 -101
  66. data/helper-scripts/rack-loader.rb +96 -96
  67. data/helper-scripts/rack-preloader.rb +137 -137
  68. data/lib/phusion_passenger.rb +292 -292
  69. data/lib/phusion_passenger/abstract_installer.rb +438 -438
  70. data/lib/phusion_passenger/active_support3_extensions/init.rb +168 -170
  71. data/lib/phusion_passenger/admin_tools.rb +20 -20
  72. data/lib/phusion_passenger/admin_tools/instance.rb +178 -178
  73. data/lib/phusion_passenger/admin_tools/instance_registry.rb +61 -61
  74. data/lib/phusion_passenger/admin_tools/memory_stats.rb +267 -267
  75. data/lib/phusion_passenger/apache2/config_options.rb +182 -182
  76. data/lib/phusion_passenger/common_library.rb +479 -485
  77. data/lib/phusion_passenger/config/about_command.rb +161 -161
  78. data/lib/phusion_passenger/config/admin_command_command.rb +129 -129
  79. data/lib/phusion_passenger/config/agent_compiler.rb +121 -121
  80. data/lib/phusion_passenger/config/build_native_support_command.rb +43 -43
  81. data/lib/phusion_passenger/config/command.rb +25 -25
  82. data/lib/phusion_passenger/config/compile_agent_command.rb +62 -62
  83. data/lib/phusion_passenger/config/compile_nginx_engine_command.rb +88 -73
  84. data/lib/phusion_passenger/config/detach_process_command.rb +72 -72
  85. data/lib/phusion_passenger/config/download_agent_command.rb +246 -227
  86. data/lib/phusion_passenger/config/download_nginx_engine_command.rb +245 -224
  87. data/lib/phusion_passenger/config/install_agent_command.rb +144 -132
  88. data/lib/phusion_passenger/config/install_standalone_runtime_command.rb +205 -185
  89. data/lib/phusion_passenger/config/installation_utils.rb +204 -204
  90. data/lib/phusion_passenger/config/list_instances_command.rb +64 -64
  91. data/lib/phusion_passenger/config/main.rb +152 -152
  92. data/lib/phusion_passenger/config/nginx_engine_compiler.rb +319 -300
  93. data/lib/phusion_passenger/config/reopen_logs_command.rb +67 -67
  94. data/lib/phusion_passenger/config/restart_app_command.rb +155 -155
  95. data/lib/phusion_passenger/config/system_metrics_command.rb +13 -13
  96. data/lib/phusion_passenger/config/utils.rb +95 -95
  97. data/lib/phusion_passenger/config/validate_install_command.rb +198 -198
  98. data/lib/phusion_passenger/console_text_template.rb +25 -25
  99. data/lib/phusion_passenger/constants.rb +90 -90
  100. data/lib/phusion_passenger/debug_logging.rb +106 -106
  101. data/lib/phusion_passenger/loader_shared_helpers.rb +447 -432
  102. data/lib/phusion_passenger/message_channel.rb +312 -312
  103. data/lib/phusion_passenger/message_client.rb +176 -176
  104. data/lib/phusion_passenger/native_support.rb +369 -369
  105. data/lib/phusion_passenger/nginx/config_options.rb +297 -297
  106. data/lib/phusion_passenger/packaging.rb +131 -131
  107. data/lib/phusion_passenger/platform_info.rb +360 -360
  108. data/lib/phusion_passenger/platform_info/apache.rb +767 -767
  109. data/lib/phusion_passenger/platform_info/apache_detector.rb +199 -199
  110. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +107 -107
  111. data/lib/phusion_passenger/platform_info/compiler.rb +570 -570
  112. data/lib/phusion_passenger/platform_info/curl.rb +32 -32
  113. data/lib/phusion_passenger/platform_info/cxx_portability.rb +188 -188
  114. data/lib/phusion_passenger/platform_info/depcheck.rb +372 -372
  115. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +109 -109
  116. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
  117. data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +10 -34
  118. data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +101 -101
  119. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -5
  120. data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +13 -13
  121. data/lib/phusion_passenger/platform_info/linux.rb +55 -55
  122. data/lib/phusion_passenger/platform_info/operating_system.rb +149 -149
  123. data/lib/phusion_passenger/platform_info/ruby.rb +468 -448
  124. data/lib/phusion_passenger/platform_info/zlib.rb +9 -9
  125. data/lib/phusion_passenger/plugin.rb +66 -66
  126. data/lib/phusion_passenger/preloader_shared_helpers.rb +126 -126
  127. data/lib/phusion_passenger/public_api.rb +191 -191
  128. data/lib/phusion_passenger/rack/out_of_band_gc.rb +93 -94
  129. data/lib/phusion_passenger/rack/thread_handler_extension.rb +231 -227
  130. data/lib/phusion_passenger/request_handler.rb +567 -577
  131. data/lib/phusion_passenger/request_handler/thread_handler.rb +379 -381
  132. data/lib/phusion_passenger/ruby_core_enhancements.rb +86 -86
  133. data/lib/phusion_passenger/ruby_core_io_enhancements.rb +74 -74
  134. data/lib/phusion_passenger/simple_benchmarking.rb +25 -25
  135. data/lib/phusion_passenger/standalone/app_finder.rb +153 -150
  136. data/lib/phusion_passenger/standalone/command.rb +44 -40
  137. data/lib/phusion_passenger/standalone/config_utils.rb +53 -53
  138. data/lib/phusion_passenger/standalone/control_utils.rb +38 -59
  139. data/lib/phusion_passenger/standalone/main.rb +73 -73
  140. data/lib/phusion_passenger/standalone/start_command.rb +697 -685
  141. data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +193 -155
  142. data/lib/phusion_passenger/standalone/start_command/nginx_engine.rb +162 -133
  143. data/lib/phusion_passenger/standalone/status_command.rb +64 -64
  144. data/lib/phusion_passenger/standalone/stop_command.rb +72 -72
  145. data/lib/phusion_passenger/standalone/version_command.rb +9 -9
  146. data/lib/phusion_passenger/union_station/connection.rb +32 -32
  147. data/lib/phusion_passenger/union_station/core.rb +251 -251
  148. data/lib/phusion_passenger/union_station/transaction.rb +126 -126
  149. data/lib/phusion_passenger/utils.rb +199 -167
  150. data/lib/phusion_passenger/utils/ansi_colors.rb +128 -128
  151. data/lib/phusion_passenger/utils/download.rb +196 -196
  152. data/lib/phusion_passenger/utils/file_system_watcher.rb +158 -158
  153. data/lib/phusion_passenger/utils/hosts_file_parser.rb +101 -101
  154. data/lib/phusion_passenger/utils/lock.rb +31 -31
  155. data/lib/phusion_passenger/utils/native_support_utils.rb +31 -31
  156. data/lib/phusion_passenger/utils/progress_bar.rb +26 -26
  157. data/lib/phusion_passenger/utils/shellwords.rb +20 -20
  158. data/lib/phusion_passenger/utils/terminal_choice_menu.rb +206 -206
  159. data/lib/phusion_passenger/utils/unseekable_socket.rb +272 -272
  160. data/lib/phusion_passenger/vendor/crash_watch/app.rb +129 -0
  161. data/lib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +341 -0
  162. data/lib/phusion_passenger/vendor/crash_watch/version.rb +24 -0
  163. data/lib/phusion_passenger/vendor/daemon_controller.rb +877 -0
  164. data/lib/phusion_passenger/vendor/daemon_controller/lock_file.rb +127 -0
  165. data/lib/phusion_passenger/vendor/daemon_controller/spawn.rb +26 -0
  166. data/lib/phusion_passenger/vendor/daemon_controller/version.rb +29 -0
  167. data/packaging/rpm/passenger_spec/passenger.spec.template +0 -1
  168. data/passenger.gemspec +0 -1
  169. data/resources/templates/config/nginx_engine_compiler/possible_solutions_for_download_and_extraction_problems.txt.erb +27 -0
  170. data/resources/templates/standalone/config.erb +19 -15
  171. data/test/integration_tests/apache2_tests.rb +566 -566
  172. data/test/integration_tests/downloaded_binaries_tests.rb +126 -125
  173. data/test/integration_tests/native_packaging_spec.rb +296 -296
  174. data/test/integration_tests/nginx_tests.rb +393 -393
  175. data/test/integration_tests/shared/example_webapp_tests.rb +282 -280
  176. data/test/integration_tests/source_packaging_test.rb +138 -138
  177. data/test/integration_tests/spec_helper.rb +5 -5
  178. data/test/integration_tests/standalone_tests.rb +367 -367
  179. data/test/ruby/debug_logging_spec.rb +133 -133
  180. data/test/ruby/message_channel_spec.rb +186 -186
  181. data/test/ruby/rack/loader_spec.rb +28 -28
  182. data/test/ruby/rack/preloader_spec.rb +34 -34
  183. data/test/ruby/rails3.0/loader_spec.rb +12 -12
  184. data/test/ruby/rails3.0/preloader_spec.rb +18 -18
  185. data/test/ruby/rails3.1/loader_spec.rb +12 -12
  186. data/test/ruby/rails3.1/preloader_spec.rb +18 -18
  187. data/test/ruby/rails3.2/loader_spec.rb +12 -12
  188. data/test/ruby/rails3.2/preloader_spec.rb +18 -18
  189. data/test/ruby/rails4.0/loader_spec.rb +12 -12
  190. data/test/ruby/rails4.0/preloader_spec.rb +18 -18
  191. data/test/ruby/rails4.1/loader_spec.rb +12 -12
  192. data/test/ruby/rails4.1/preloader_spec.rb +18 -18
  193. data/test/ruby/request_handler_spec.rb +730 -730
  194. data/test/ruby/shared/loader_sharedspec.rb +224 -224
  195. data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +327 -327
  196. data/test/ruby/shared/ruby_loader_sharedspec.rb +47 -47
  197. data/test/ruby/spec_helper.rb +65 -65
  198. data/test/ruby/standalone/runtime_installer_spec.rb +384 -384
  199. data/test/ruby/union_station_spec.rb +276 -276
  200. data/test/ruby/utils/file_system_watcher_spec.rb +220 -220
  201. data/test/ruby/utils/hosts_file_parser.rb +248 -248
  202. data/test/ruby/utils/tee_input_spec.rb +215 -215
  203. data/test/ruby/utils/unseekable_socket_spec.rb +57 -57
  204. data/test/ruby/utils_spec.rb +21 -21
  205. data/test/stub/rack/config.ru +87 -87
  206. data/test/stub/rack/library.rb +8 -8
  207. data/test/stub/rack/start.rb +30 -30
  208. data/test/support/apache2_controller.rb +191 -191
  209. data/test/support/nginx_controller.rb +90 -99
  210. data/test/support/placebo-preloader.rb +57 -57
  211. data/test/support/test_helper.rb +435 -435
  212. metadata +11 -21
  213. metadata.gz.asc +7 -7
  214. data/lib/phusion_passenger/standalone/command2.rb +0 -292
  215. data/lib/phusion_passenger/standalone/start2_command.rb +0 -799
  216. data/resources/templates/standalone/download_tool_missing.txt.erb +0 -18
  217. data/resources/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -17
  218. data/resources/templates/standalone/run_installer_as_root.txt.erb +0 -8
data/dev/runner CHANGED
@@ -9,25 +9,25 @@ require File.expand_path(File.dirname(__FILE__) + "/../lib/phusion_passenger")
9
9
  PhusionPassenger.locate_directories
10
10
 
11
11
  while true
12
- if ARGV[0] =~ /^-r(.*)/
13
- if $1.empty?
14
- lib = ARGV[1]
15
- ARGV.shift
16
- ARGV.shift
17
- else
18
- lib = $1
19
- ARGV.shift
20
- end
21
- begin
22
- PhusionPassenger.require_passenger_lib(lib)
23
- rescue LoadError
24
- require(lib)
25
- end
26
- else
27
- break
28
- end
12
+ if ARGV[0] =~ /^-r(.*)/
13
+ if $1.empty?
14
+ lib = ARGV[1]
15
+ ARGV.shift
16
+ ARGV.shift
17
+ else
18
+ lib = $1
19
+ ARGV.shift
20
+ end
21
+ begin
22
+ PhusionPassenger.require_passenger_lib(lib)
23
+ rescue LoadError
24
+ require(lib)
25
+ end
26
+ else
27
+ break
28
+ end
29
29
  end
30
30
 
31
31
  module PhusionPassenger
32
- p eval(ARGV.join(" "))
32
+ p eval(ARGV.join(" "))
33
33
  end
@@ -307,14 +307,67 @@ If you cannot use the event MPM, consider putting Apache behind an Nginx reverse
307
307
 
308
308
  ### Turbocaching
309
309
 
310
- Phusion Passenger supports turbocaching since version 4. Turbocaching is an HTTP cache built inside Phusion Passenger. When used correctly, the cache can accelerate your app tremendously.
310
+ Phusion Passenger supports turbocaching since version 4. Turbocaching is an HTTP cache built inside Phusion Passenger. When used correctly, the cache can accelerate your app tremendously. To utilize turbocaching, you only need to set HTTP caching headers.
311
311
 
312
- To utilize turbocaching, you only need to set HTTP caching headers. Please refer to [Google's HTTP caching tutorial](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching). Phusion Passenger takes advantage of the HTTP headers automatically.
312
+ #### Learning about HTTP caching headers
313
+
314
+ The first thing you should do is to [learn how to use HTTP caching headers](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching). It's pretty simple and straightforward. Since the turbocache is just a normal HTTP shared cache, it respects all the HTTP caching rules.
315
+
316
+ #### Set an Expires or Cache-Control header
317
+
318
+ To activate the turbocache, the response must contain either an "Expires" header or a "Cache-Control" header.
319
+
320
+ The "Expires" header tells the turbocache how long to cache a response. Its value is an HTTP timestamp, e.g. "Thu, 01 Dec 1994 16:00:00 GMT".
321
+
322
+ The Cache-Control header is a more advanced header that not only allows you to set the caching time, but also how the cache should behave. The easiest way to use it is to set the **max-age** flag, which has the same effect as setting "Expires". For example, this tells the turbocache that the response is cacheable for at most 60 seconds:
323
+
324
+ Cache-Control: max-age=60
325
+
326
+ As you can see, a "Cache-Control" header is much easier to generate than an "Expires" header. Furthermore, "Expires" doesn't work if the visitor's computer's clock is wrongly configured, while "Cache-Control" does. This is why we recommend using "Cache-Control".
327
+
328
+ Another flag to be aware of is the **private** flag. This flag tells any shared caches -- caches which are meant to store responses for many users -- not to cache the response. The turbocache is a shared cache. However, the browser's cache is not, so the browser can still cache the response. You should set the "private" flag on responses which are meant for a single user, as you will learn later in this article.
329
+
330
+ And finally, there is the **no-store** flag, which tells *all* caches -- even the browser's -- not to cache the response.
331
+
332
+ Here is an example of a response which is cacheable for 60 seconds by the browser's cache, but not by the turbocache:
333
+
334
+ Cache-Control: max-age=60,private
335
+
336
+ The HTTP specification specifies a bunch of other flags, but they're not relevant for the turbocache.
337
+
338
+ #### Only GET requests are cacheable
339
+
340
+ The turbocache currently only caches GET requests. POST, PUT, DELETE and other requests are never cached. If you want your response to be cacheable by the turbocache, be sure to use GET requests, but also be sure that your request is idempotent.
341
+
342
+ #### Avoid using the "Vary" header
343
+
344
+ The "Vary" header is used to tell caches that the response depends on one or more request headers. But the turbocache does not implement support for the "Vary" header, so if you output a "Vary" header then the turbocache will not cache your response at all. Avoid using the "Vary" header where possible.
313
345
 
314
346
  ### Out-of-band garbage collection
315
347
 
316
348
  Phusion Passenger supports out-of-band garbage collection for Ruby apps. With this feature enabled, Phusion Passenger can run the garbage collector in between requests, so that the garbage collector doesn't delay the app as much. Please refer to the Users Guide for more information about this feature.
317
349
 
350
+ ### Using the builtin HTTP engine
351
+
352
+ In certain situations, using the builtin HTTP engine in Passenger Standalone may yield some performance benefits because it skips a layer of processing.
353
+
354
+ Passenger normally works by integrating into Nginx or Apache. As described in the [Design & Architecture](Design%20and%20architecture.html) document, requests are first handled by Nginx or Apache, and then forwarded to the Passenger core process (the HelperAgent) and the application process. This architecture provides various benefits, such as security benefits (Nginx and Apache's HTTP connection handling routines are thoroughly battle-tested and secure) and feature benefits (e.g. Gzip compression, superb static file handling).
355
+
356
+ This is even true if you use the Standalone mode. Although it acts standalone, it is implemented under the hood by running Passenger in a builtin Nginx engine.
357
+
358
+ However, the fact that all requests go through Nginx or Apache means that there is a slight overhead, which can be avoided. This overhead is small (much smaller than typical application and network overhead), and using Nginx or Apache is very useful, but in certain special situations it may be beneficial to skip this layer.
359
+
360
+ * In **microbenchmarks**, the overhead of Nginx and Apache are very noticeable. Removing Nginx and Apache from the setup, and benchmarking against the Passenger HelperAgent directly, will yield much better results.
361
+ * In some **multi-server setups**, Nginx and Apache may be redundant. Recall that in typical multi-server setups there is a load balancer which forwards requests to one of the many web servers. Each web server in this setup runs Passenger. But the load balancer is sometimes already responsible for many of the tasks that Nginx and Apache perform, e.g. the secure handling of HTTP connections, buffering, slow client protection or even static file serving. In these cases, removing Nginx and Apache from the web servers and load balancing to the Passenger HelperAgent directly may have a minor improvement on performance.
362
+
363
+ Nginx and Apache can be removed by using Passenger's builtin HTTP engine. By using this engine, Passenger will listen directly on a socket for HTTP requests, without using Nginx or Apache.
364
+
365
+ This builtin HTTP engine can be accessed by starting Passenger Standalone using the `--engine=builtin` parameter, like this:
366
+
367
+ passenger start --engine=builtin
368
+
369
+ It should be noted that the builtin HTTP engine has fewer features than the Nginx engine, by design. For example the builtin HTTP engine does not support serving static files, nor does it support gzip compression. Thus, we recommend using the Nginx engine in most situations, unless you have special needs such as documented above.
370
+
318
371
  ## Benchmarking recommendations
319
372
 
320
373
  ### Tooling recommendations
@@ -430,32 +430,6 @@ Please see <<deploying_a_rack_app,Deploying a Rack-based Ruby application>>
430
430
  and <<deploying_a_wsgi_app,Deploying a WSGI (Python) application>>
431
431
  for examples.
432
432
 
433
- .This configuration option is NOT inherited across contexts
434
- [WARNING]
435
- ===============================================
436
- In each new context (e.g. in each new 'location' block), you must re-specify `passenger_enabled`. Values set in parent contexts have no effect on subcontexts. For example:
437
-
438
- ------------------------------
439
- server {
440
- ...
441
- passenger_enabled on;
442
-
443
- location /users {
444
- passenger_set_header X-Foo bar;
445
- # !!!THIS IS WRONG!!! We did not re-specify 'passenger_enabled on'
446
- # here, so Phusion Passenger will not handle requests that begin with
447
- # /users.
448
- }
449
-
450
- location /apps {
451
- passenger_enabled on;
452
- passenger_set_header X-Foo bar;
453
- # This is correct. Here we re-specify 'passenger_enabled'.
454
- }
455
- }
456
- ------------------------------
457
- ===============================================
458
-
459
433
  [[PassengerBaseURI]]
460
434
  ==== passenger_base_uri <uri>
461
435
  Used to specify that the given URI is an distinct application that should
@@ -100,8 +100,12 @@ The following configuration options are supported:
100
100
  `ssl_port`::
101
101
  Equivalent to the `--ssl-port` command line option.
102
102
  +
103
- When in mass deployment mode, you will probably want to set a different `port` too. If you don't, and you end up in a situation in which a port is used for both HTTP and HTTPS traffic, then the builtin Nginx core will abort with an error.
103
+ When in <<mass_deployment,mass deployment mode>>, you will probably want to set a different `port` too. If you don't, and you end up in a situation in which a port is used for both HTTP and HTTPS traffic, then the builtin Nginx core will abort with an error.
104
104
 
105
+ `server_names` (Enterprise only)::
106
+ Only relevant in <<mass_deployment,mass deployment mode>>. This option specifies which server names (host names) should be routed to this application. This option must be an array of names, e.g. `"server_names": ["foo.com", "bar.com"]`. By default, the name of the application directory is used as the server name. For example, for an application located in /webapps/foobar.com, "foobar.com" is used as the server name.
107
+ `envvars` (since 5.0.0 RC 1)::
108
+ Environment variables to pass to the application. This option must be a key-value map, e.g. `"envvars": { "ADMIN_EMAIL": "root@phusion.nl", "SECRET_KEY": "12345" }`.
105
109
  `nginx_config_template`::
106
110
  Equivalent to the `--nginx-config-template` command line option.
107
111
 
@@ -487,6 +487,10 @@ Because hooks are inherently tied to the implementation of Phusion Passenger, th
487
487
  Called at the very beginning of Phusion Passenger's life cycle, during the start of the Watchdog process. The first hook is called before initialization is performed (before the HelperAgent is started). Errors in the hook script cause Phusion Passenger to abort.
488
488
  `after_watchdog_initialization`::
489
489
  Like `before_watchdog_initialization`, but called after initialization of all Phusion Passenger agent processes. Errors in the hook script cause Phusion Passenger to abort.
490
+ `before_watchdog_shutdown`::
491
+ Called after an exit signal has been noticed (e.g. webserver exit), before the Watchdog starts terminating agents
492
+ `after_watchdog_shutdown`::
493
+ Called after the Watchdog is done and about to exit
490
494
  `attached_process`::
491
495
  Called when Phusion Passenger has successfully spawned an application processes and added it to the process pool. Extra environment variables: `PASSENGER_PROCESS_PID`, `PASSENGER_APP_ROOT`. Errors in the hook script are ignored.
492
496
  `detached_process`::
@@ -507,6 +511,11 @@ Extra environment variables: `PASSENGER_PROCESS_PID`, `PASSENGER_APP_ROOT`. Erro
507
511
  - Operating system-level problems, such as running out of memory.
508
512
  - The application taking too long to start, and hitting Phusion Passenger's timeout.
509
513
 
514
+ +
515
+ `queue_full_error` (since 5.0.0 RC 1)::
516
+ The server rejects new requests (default: HTTP 503) while the request queue is full (https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html#passenger_max_request_queue_size).
517
+ This hook gets called for each rejection.
518
+
510
519
  +
511
520
  Extra environment variables:
512
521
  +
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2014 Phusion
3
+ * Copyright (c) 2011-2015 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -206,9 +206,9 @@ public:
206
206
  unsigned int restartsInitiated);
207
207
  void spawnThreadRealMain(const SpawnerPtr &spawner, const Options &options,
208
208
  unsigned int restartsInitiated);
209
- void finalizeRestart(GroupPtr self, Options options, RestartMethod method,
210
- SpawnerFactoryPtr spawnerFactory, unsigned int restartsInitiated,
211
- boost::container::vector<Callback> postLockActions);
209
+ void finalizeRestart(GroupPtr self, Options oldOptions, Options newOptions,
210
+ RestartMethod method, SpawnerFactoryPtr spawnerFactory,
211
+ unsigned int restartsInitiated, boost::container::vector<Callback> postLockActions);
212
212
  void startCheckingDetachedProcesses(bool immediately);
213
213
  void detachedProcessesCheckerMain(GroupPtr self);
214
214
  void wakeUpGarbageCollector();
@@ -221,6 +221,7 @@ public:
221
221
  void callAbortLongRunningConnectionsCallback(const ProcessPtr &process);
222
222
  psg_pool_t *getPallocPool() const;
223
223
  const ResourceLocator &getResourceLocator() const;
224
+ bool prepareHookScriptOptions(HookScriptOptions &hsOptions, const char *name);
224
225
  void runAttachHooks(const ProcessPtr process) const;
225
226
  void runDetachHooks(const ProcessPtr process) const;
226
227
  void setupAttachOrDetachHook(const ProcessPtr process, HookScriptOptions &options) const;
@@ -328,14 +329,18 @@ public:
328
329
  #endif
329
330
 
330
331
  /**
331
- * Sets options for this Group. Called at creation time and at restart time.
332
+ * Persists options into this Group. Called at creation time and at restart time.
333
+ * Values will be persisted into `destination`. Or if it's NULL, into `this->options`.
332
334
  */
333
- void resetOptions(const Options &newOptions) {
334
- options = newOptions;
335
- options.persist(newOptions);
336
- options.clearPerRequestFields();
337
- options.groupSecret = StaticString(secret, SECRET_SIZE);
338
- options.groupUuid = uuid;
335
+ void resetOptions(const Options &newOptions, Options *destination = NULL) {
336
+ if (destination == NULL) {
337
+ destination = &this->options;
338
+ }
339
+ *destination = newOptions;
340
+ destination->persist(newOptions);
341
+ destination->clearPerRequestFields();
342
+ destination->groupSecret = StaticString(secret, SECRET_SIZE);
343
+ destination->groupUuid = uuid;
339
344
  }
340
345
 
341
346
  /**
@@ -442,6 +447,13 @@ public:
442
447
  P_WARN("Request queue is full. Returning an error");
443
448
  postLockActions.push_back(boost::bind(GetCallback::call,
444
449
  callback, SessionPtr(), boost::make_shared<RequestQueueFullException>()));
450
+
451
+ HookScriptOptions hsOptions;
452
+ if (prepareHookScriptOptions(hsOptions, "queue_full_error")) {
453
+ // TODO <Feb 17, 2015] DK> should probably rate limit this, since we are already at heavy load
454
+ postLockActions.push_back(boost::bind(runHookScripts, hsOptions));
455
+ }
456
+
445
457
  return false;
446
458
  }
447
459
  }
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2014 Phusion
3
+ * Copyright (c) 2011-2015 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -526,13 +526,14 @@ SuperGroup::realDoRestart(const Options &options, unsigned int generation) {
526
526
  }
527
527
 
528
528
 
529
- Group::Group(SuperGroup *_superGroup, const Options &options, const ComponentInfo &info)
529
+ Group::Group(SuperGroup *_superGroup, const Options &_options, const ComponentInfo &info)
530
530
  : superGroup(_superGroup),
531
531
  name(_superGroup->name + "#" + info.name),
532
532
  uuid(generateUuid(_superGroup)),
533
533
  componentInfo(info)
534
534
  {
535
535
  generateSecret(_superGroup, secret);
536
+ resetOptions(_options);
536
537
  enabledCount = 0;
537
538
  disablingCount = 0;
538
539
  disabledCount = 0;
@@ -556,7 +557,6 @@ Group::Group(SuperGroup *_superGroup, const Options &options, const ComponentInf
556
557
  restartFile = options.appRoot + "/" + options.restartDir + "/restart.txt";
557
558
  alwaysRestartFile = options.appRoot + "/" + options.restartDir + "/always_restart.txt";
558
559
  }
559
- resetOptions(options);
560
560
 
561
561
  detachedProcessesCheckerActive = false;
562
562
  }
@@ -1181,6 +1181,7 @@ Group::restart(const Options &options, RestartMethod method) {
1181
1181
  detachAll(actions);
1182
1182
  getPool()->interruptableThreads.create_thread(
1183
1183
  boost::bind(&Group::finalizeRestart, this, shared_from_this(),
1184
+ this->options.copyAndPersist().clearPerRequestFields(),
1184
1185
  options.copyAndPersist().clearPerRequestFields(),
1185
1186
  method, getPool()->spawnerFactory, restartsInitiated, actions),
1186
1187
  "Group restarter: " + name,
@@ -1190,8 +1191,11 @@ Group::restart(const Options &options, RestartMethod method) {
1190
1191
 
1191
1192
  // The 'self' parameter is for keeping the current Group object alive while this thread is running.
1192
1193
  void
1193
- Group::finalizeRestart(GroupPtr self, Options options, RestartMethod method,
1194
- SpawnerFactoryPtr spawnerFactory, unsigned int restartsInitiated,
1194
+ Group::finalizeRestart(GroupPtr self,
1195
+ Options oldOptions,
1196
+ Options newOptions, RestartMethod method,
1197
+ SpawnerFactoryPtr spawnerFactory,
1198
+ unsigned int restartsInitiated,
1195
1199
  boost::container::vector<Callback> postLockActions)
1196
1200
  {
1197
1201
  TRACE_POINT();
@@ -1203,7 +1207,9 @@ Group::finalizeRestart(GroupPtr self, Options options, RestartMethod method,
1203
1207
  this_thread::disable_syscall_interruption dsi;
1204
1208
 
1205
1209
  // Create a new spawner.
1206
- SpawnerPtr newSpawner = spawnerFactory->create(options);
1210
+ Options spawnerOptions = oldOptions;
1211
+ resetOptions(newOptions, &spawnerOptions);
1212
+ SpawnerPtr newSpawner = spawnerFactory->create(spawnerOptions);
1207
1213
  SpawnerPtr oldSpawner;
1208
1214
 
1209
1215
  UPDATE_TRACE_POINT();
@@ -1239,7 +1245,7 @@ Group::finalizeRestart(GroupPtr self, Options options, RestartMethod method,
1239
1245
  UPDATE_TRACE_POINT();
1240
1246
 
1241
1247
  // Atomically swap the new spawner with the old one.
1242
- resetOptions(options);
1248
+ resetOptions(newOptions);
1243
1249
  oldSpawner = spawner;
1244
1250
  spawner = newSpawner;
1245
1251
 
@@ -1464,6 +1470,25 @@ Group::getResourceLocator() const {
1464
1470
  return *getPool()->getSpawnerConfig()->resourceLocator;
1465
1471
  }
1466
1472
 
1473
+ /* Given a hook name like "queue_full_error", we return HookScriptOptions filled in with this name and a spec
1474
+ * (user settings that can be queried from agentsOptions using the external hook name that is prefixed with "hook_")
1475
+
1476
+ * @return false if the user parameters (agentsOptions) are not available (e.g. during ApplicationPool2_PoolTest)
1477
+ */
1478
+ bool
1479
+ Group::prepareHookScriptOptions(HookScriptOptions &hsOptions, const char *name) {
1480
+ SpawnerConfigPtr config = getPool()->getSpawnerConfig();
1481
+ if (config->agentsOptions == NULL) {
1482
+ return false;
1483
+ }
1484
+
1485
+ hsOptions.name = name;
1486
+ string hookName = string("hook_") + name;
1487
+ hsOptions.spec = config->agentsOptions->get(hookName, false);
1488
+
1489
+ return true;
1490
+ }
1491
+
1467
1492
  // 'process' is not a reference so that bind(runAttachHooks, ...) causes the shared
1468
1493
  // pointer reference to increment.
1469
1494
  void
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2014 Phusion
3
+ * Copyright (c) 2011-2015 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -827,8 +827,24 @@ public:
827
827
  while (!this_thread::interruption_requested()) {
828
828
  try {
829
829
  UPDATE_TRACE_POINT();
830
- unsigned long long sleepTime = self->realCollectAnalytics();
831
- syscalls::usleep(sleepTime);
830
+ self->realCollectAnalytics();
831
+ } catch (const thread_interrupted &) {
832
+ break;
833
+ } catch (const tracable_exception &e) {
834
+ P_WARN("ERROR: " << e.what() << "\n Backtrace:\n" << e.backtrace());
835
+ }
836
+
837
+ // Sleep for about 4 seconds, aligned to seconds boundary
838
+ // for saving power on laptops.
839
+ UPDATE_TRACE_POINT();
840
+ unsigned long long currentTime = SystemTime::getUsec();
841
+ unsigned long long deadline =
842
+ roundUp<unsigned long long>(currentTime, 1000000) + 4000000;
843
+ P_DEBUG("Analytics collection done; next analytics collection in " <<
844
+ std::fixed << std::setprecision(3) << ((deadline - currentTime) / 1000000.0) <<
845
+ " sec");
846
+ try {
847
+ syscalls::usleep(deadline - currentTime);
832
848
  } catch (const thread_interrupted &) {
833
849
  break;
834
850
  } catch (const tracable_exception &e) {
@@ -902,7 +918,7 @@ public:
902
918
  }
903
919
  }
904
920
 
905
- unsigned long long realCollectAnalytics() {
921
+ void realCollectAnalytics() {
906
922
  TRACE_POINT();
907
923
  this_thread::disable_interruption di;
908
924
  this_thread::disable_syscall_interruption dsi;
@@ -944,14 +960,14 @@ public:
944
960
  processMetrics = ProcessMetricsCollector().collect(pids);
945
961
  } catch (const ParseException &) {
946
962
  P_WARN("Unable to collect process metrics: cannot parse 'ps' output.");
947
- goto end;
963
+ return;
948
964
  }
949
965
  try {
950
966
  UPDATE_TRACE_POINT();
951
967
  systemMetricsCollector.collect(systemMetrics);
952
968
  } catch (const RuntimeException &e) {
953
969
  P_WARN("Unable to collect system metrics: " << e.what());
954
- goto end;
970
+ return;
955
971
  }
956
972
 
957
973
  {
@@ -1008,17 +1024,6 @@ public:
1008
1024
  // Run destructors with updated trace point.
1009
1025
  actions.clear();
1010
1026
  }
1011
-
1012
- end:
1013
- // Sleep for about 4 seconds, aligned to seconds boundary
1014
- // for saving power on laptops.
1015
- unsigned long long currentTime = SystemTime::getUsec();
1016
- unsigned long long deadline =
1017
- roundUp<unsigned long long>(currentTime, 1000000) + 4000000;
1018
- P_DEBUG("Analytics collection done; next analytics collection in " <<
1019
- std::fixed << std::setprecision(3) << ((deadline - currentTime) / 1000000.0) <<
1020
- " sec");
1021
- return deadline - currentTime;
1022
1027
  }
1023
1028
 
1024
1029
  SuperGroupPtr createSuperGroup(const Options &options) {
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2014 Phusion
3
+ * Copyright (c) 2011-2015 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -339,6 +339,9 @@ private:
339
339
  "ruby_libdir: " + config->resourceLocator->getRubyLibDir() + "\n"
340
340
  "passenger_version: " PASSENGER_VERSION "\n"
341
341
  "UNIX_PATH_MAX: " + toString(UNIX_PATH_MAX) + "\n";
342
+ if (!details.options->groupSecret.empty()) {
343
+ data.append("connect_password: " + details.options->groupSecret + "\n");
344
+ }
342
345
  if (!config->instanceDir.empty()) {
343
346
  data.append("socket_dir: " + config->instanceDir + "/apps.s\n");
344
347
  }