passenger 2.1.3 → 2.2.0
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/DEVELOPERS.TXT +2 -0
- data/INSTALL +3 -1
- data/LICENSE +19 -355
- data/NEWS +3 -0
- data/README +11 -4
- data/Rakefile +435 -236
- data/bin/passenger-config +20 -14
- data/bin/passenger-install-apache2-module +67 -201
- data/bin/passenger-install-nginx-module +477 -0
- data/bin/passenger-make-enterprisey +17 -12
- data/bin/passenger-memory-stats +33 -23
- data/bin/passenger-spawn-server +17 -12
- data/bin/passenger-status +18 -13
- data/bin/passenger-stress-test +17 -12
- data/doc/{Users guide.html → Users guide Apache.html } +79 -61
- data/doc/{Users guide.txt → Users guide Apache.txt } +43 -939
- data/doc/Users guide Nginx.html +2276 -0
- data/doc/Users guide Nginx.txt +776 -0
- data/doc/cxxapi/ApplicationPoolServer_8h-source.html +9 -4
- data/doc/cxxapi/ApplicationPool_8h-source.html +9 -4
- data/doc/cxxapi/Application_8h-source.html +26 -21
- data/doc/cxxapi/Bucket_8h-source.html +54 -44
- data/doc/cxxapi/CachedFileStat_8h-source.html +9 -4
- data/doc/cxxapi/Configuration_8h-source.html +357 -339
- data/doc/cxxapi/DirectoryMapper_8h-source.html +294 -280
- data/doc/cxxapi/DummySpawnManager_8h-source.html +9 -4
- data/doc/cxxapi/Exceptions_8h-source.html +9 -4
- data/doc/cxxapi/FileChecker_8h-source.html +9 -4
- data/doc/cxxapi/Hooks_8h-source.html +50 -40
- data/doc/cxxapi/Logging_8h-source.html +9 -4
- data/doc/cxxapi/MessageChannel_8h-source.html +20 -15
- data/doc/cxxapi/PoolOptions_8h-source.html +10 -5
- data/doc/cxxapi/SpawnManager_8h-source.html +9 -4
- data/doc/cxxapi/StandardApplicationPool_8h-source.html +10 -5
- data/doc/cxxapi/SystemTime_8h-source.html +9 -4
- data/doc/cxxapi/Utils_8h-source.html +242 -214
- data/doc/cxxapi/annotated.html +4 -28
- data/doc/cxxapi/classClient-members.html +4 -4
- data/doc/cxxapi/classClient.html +14 -11
- data/doc/cxxapi/classHooks-members.html +4 -5
- data/doc/cxxapi/classHooks.html +26 -24
- data/doc/cxxapi/classPassenger_1_1Application-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1Application.html +40 -37
- data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +95 -92
- data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +26 -23
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +17 -17
- data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +139 -136
- data/doc/cxxapi/classPassenger_1_1BufferedUpload-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1BufferedUpload.html +13 -10
- data/doc/cxxapi/classPassenger_1_1BusyException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1BusyException.html +11 -8
- data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +11 -8
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +4 -5
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +45 -43
- data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +13 -10
- data/doc/cxxapi/classPassenger_1_1FileChecker-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1FileChecker.html +22 -19
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +12 -9
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1FileSystemException.html +14 -11
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1IOException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1IOException.html +12 -9
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1MessageChannel.html +228 -225
- data/doc/cxxapi/classPassenger_1_1RuntimeException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1RuntimeException.html +11 -8
- data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1SpawnException.html +14 -11
- data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1SpawnManager.html +50 -47
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +73 -70
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1SystemException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1SystemException.html +17 -14
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1SystemTime-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1SystemTime.html +14 -11
- data/doc/cxxapi/classes.html +35 -0
- data/doc/cxxapi/definitions_8h-source.html +9 -4
- data/doc/cxxapi/doxygen.css +311 -303
- data/doc/cxxapi/files.html +9 -18
- data/doc/cxxapi/functions.html +5 -224
- data/doc/cxxapi/functions_func.html +5 -185
- data/doc/cxxapi/functions_type.html +4 -4
- data/doc/cxxapi/functions_vars.html +4 -4
- data/doc/cxxapi/graph_legend.dot +19 -19
- data/doc/cxxapi/graph_legend.html +5 -5
- data/doc/cxxapi/graph_legend.png +0 -0
- data/doc/cxxapi/group__Configuration.html +11 -13
- data/doc/cxxapi/group__Configuration.png +0 -0
- data/doc/cxxapi/group__Core.html +10 -12
- data/doc/cxxapi/group__Core.png +0 -0
- data/doc/cxxapi/group__Exceptions.html +5 -7
- data/doc/cxxapi/group__Hooks.html +5 -7
- data/doc/cxxapi/group__Hooks.png +0 -0
- data/doc/cxxapi/group__Support.html +5 -624
- data/doc/cxxapi/hierarchy.html +6 -6
- data/doc/cxxapi/inherit__graph__0.map +1 -1
- data/doc/cxxapi/inherit__graph__0.md5 +1 -1
- data/doc/cxxapi/inherit__graph__0.png +0 -0
- data/doc/cxxapi/inherit__graph__1.map +1 -1
- data/doc/cxxapi/inherit__graph__1.md5 +1 -1
- data/doc/cxxapi/inherit__graph__1.png +0 -0
- data/doc/cxxapi/inherit__graph__10.map +1 -1
- data/doc/cxxapi/inherit__graph__10.md5 +1 -1
- data/doc/cxxapi/inherit__graph__10.png +0 -0
- data/doc/cxxapi/inherit__graph__11.map +1 -1
- data/doc/cxxapi/inherit__graph__11.md5 +1 -1
- data/doc/cxxapi/inherit__graph__11.png +0 -0
- data/doc/cxxapi/inherit__graph__12.map +1 -1
- data/doc/cxxapi/inherit__graph__12.md5 +1 -1
- data/doc/cxxapi/inherit__graph__12.png +0 -0
- data/doc/cxxapi/inherit__graph__13.map +1 -2
- data/doc/cxxapi/inherit__graph__13.md5 +1 -1
- data/doc/cxxapi/inherit__graph__13.png +0 -0
- data/doc/cxxapi/inherit__graph__14.map +2 -1
- data/doc/cxxapi/inherit__graph__14.md5 +1 -1
- data/doc/cxxapi/inherit__graph__14.png +0 -0
- data/doc/cxxapi/inherit__graph__15.map +1 -1
- data/doc/cxxapi/inherit__graph__15.md5 +1 -1
- data/doc/cxxapi/inherit__graph__15.png +0 -0
- data/doc/cxxapi/inherit__graph__16.map +1 -1
- data/doc/cxxapi/inherit__graph__16.md5 +1 -1
- data/doc/cxxapi/inherit__graph__16.png +0 -0
- data/doc/cxxapi/inherit__graph__17.map +1 -1
- data/doc/cxxapi/inherit__graph__17.md5 +1 -1
- data/doc/cxxapi/inherit__graph__17.png +0 -0
- data/doc/cxxapi/inherit__graph__18.map +1 -1
- data/doc/cxxapi/inherit__graph__18.md5 +1 -1
- data/doc/cxxapi/inherit__graph__18.png +0 -0
- data/doc/cxxapi/inherit__graph__19.map +1 -1
- data/doc/cxxapi/inherit__graph__19.md5 +1 -1
- data/doc/cxxapi/inherit__graph__19.png +0 -0
- data/doc/cxxapi/inherit__graph__2.map +1 -1
- data/doc/cxxapi/inherit__graph__2.md5 +1 -1
- data/doc/cxxapi/inherit__graph__2.png +0 -0
- data/doc/cxxapi/inherit__graph__20.map +2 -2
- data/doc/cxxapi/inherit__graph__20.md5 +1 -1
- data/doc/cxxapi/inherit__graph__20.png +0 -0
- data/doc/cxxapi/inherit__graph__21.map +1 -1
- data/doc/cxxapi/inherit__graph__21.md5 +1 -1
- data/doc/cxxapi/inherit__graph__21.png +0 -0
- data/doc/cxxapi/inherit__graph__3.map +1 -1
- data/doc/cxxapi/inherit__graph__3.md5 +1 -1
- data/doc/cxxapi/inherit__graph__3.png +0 -0
- data/doc/cxxapi/inherit__graph__4.map +1 -1
- data/doc/cxxapi/inherit__graph__4.md5 +1 -1
- data/doc/cxxapi/inherit__graph__4.png +0 -0
- data/doc/cxxapi/inherit__graph__5.map +1 -2
- data/doc/cxxapi/inherit__graph__5.md5 +1 -1
- data/doc/cxxapi/inherit__graph__5.png +0 -0
- data/doc/cxxapi/inherit__graph__6.map +2 -1
- data/doc/cxxapi/inherit__graph__6.md5 +1 -1
- data/doc/cxxapi/inherit__graph__6.png +0 -0
- data/doc/cxxapi/inherit__graph__7.map +1 -1
- data/doc/cxxapi/inherit__graph__7.md5 +1 -1
- data/doc/cxxapi/inherit__graph__7.png +0 -0
- data/doc/cxxapi/inherit__graph__8.map +1 -1
- data/doc/cxxapi/inherit__graph__8.md5 +1 -1
- data/doc/cxxapi/inherit__graph__8.png +0 -0
- data/doc/cxxapi/inherit__graph__9.map +1 -1
- data/doc/cxxapi/inherit__graph__9.md5 +1 -1
- data/doc/cxxapi/inherit__graph__9.png +0 -0
- data/doc/cxxapi/inherits.html +41 -41
- data/doc/cxxapi/main.html +4 -4
- data/doc/cxxapi/modules.html +4 -5
- data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +4 -4
- data/doc/cxxapi/structPassenger_1_1AnythingToString.html +13 -10
- data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +5 -5
- data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +16 -13
- data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +4 -4
- data/doc/cxxapi/structPassenger_1_1PoolOptions.html +63 -60
- data/doc/cxxapi/tabs.css +5 -2
- data/doc/cxxapi/tree.html +7 -81
- data/doc/rdoc/classes/ConditionVariable.html +59 -59
- data/doc/rdoc/classes/Exception.html +11 -11
- data/doc/rdoc/classes/GC.html +4 -4
- data/doc/rdoc/classes/IO.html +14 -14
- data/doc/rdoc/classes/PhusionPassenger.html +75 -20
- data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +153 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +125 -130
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +236 -236
- data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +213 -213
- data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +28 -28
- data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +91 -75
- data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +10 -10
- data/doc/rdoc/classes/PhusionPassenger/Application.html +64 -64
- data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +34 -34
- data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +13 -13
- data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +30 -30
- data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +10 -10
- data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +136 -136
- data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +24 -24
- data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +42 -42
- data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +55 -53
- data/doc/rdoc/classes/PhusionPassenger/Railz.html +1 -1
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +25 -30
- data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +23 -23
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +116 -117
- data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +22 -22
- data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +118 -124
- data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +10 -10
- data/doc/rdoc/classes/PhusionPassenger/Utils.html +354 -354
- data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +9 -9
- data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +37 -37
- data/doc/rdoc/classes/PlatformInfo.html +282 -261
- data/doc/rdoc/classes/RakeExtensions.html +7 -7
- data/doc/rdoc/classes/Signal.html +26 -26
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/DEVELOPERS_TXT.html +6 -1
- data/doc/rdoc/files/README.html +15 -6
- data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +129 -0
- data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +20 -13
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +31 -1
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +31 -1
- data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +21 -12
- data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +22 -12
- data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +21 -12
- data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +21 -12
- data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +27 -21
- data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +21 -12
- data/doc/rdoc/files/misc/rake/extensions_rb.html +21 -12
- data/doc/rdoc/fr_class_index.html +1 -0
- data/doc/rdoc/fr_file_index.html +2 -0
- data/doc/rdoc/fr_method_index.html +116 -112
- data/doc/users_guide_snippets/analysis_and_system_maintenance_tools.txt +144 -0
- data/doc/users_guide_snippets/appendix_a_about.txt +13 -0
- data/doc/users_guide_snippets/appendix_b_terminology.txt +63 -0
- data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +304 -0
- data/doc/users_guide_snippets/global_queueing_explained.txt +78 -0
- data/doc/users_guide_snippets/rackup_specifications.txt +75 -0
- data/doc/users_guide_snippets/rails_spawn_method.txt +48 -0
- data/doc/users_guide_snippets/tips.txt +173 -0
- data/ext/apache2/Bucket.cpp +17 -12
- data/ext/apache2/Bucket.h +17 -12
- data/ext/apache2/Configuration.cpp +17 -12
- data/ext/apache2/Configuration.h +27 -14
- data/ext/apache2/DirectoryMapper.h +21 -12
- data/ext/apache2/Hooks.cpp +67 -21
- data/ext/apache2/Hooks.h +17 -12
- data/ext/apache2/mod_passenger.c +17 -12
- data/ext/{apache2 → common}/Application.h +19 -14
- data/ext/{apache2 → common}/ApplicationPool.h +17 -12
- data/ext/{apache2 → common}/ApplicationPoolServer.h +18 -72
- data/ext/{apache2 → common}/ApplicationPoolServerExecutable.cpp +45 -104
- data/ext/common/ApplicationPoolStatusReporter.h +212 -0
- data/ext/{apache2 → common}/CachedFileStat.cpp +17 -12
- data/ext/{apache2 → common}/CachedFileStat.h +17 -12
- data/ext/{apache2 → common}/DummySpawnManager.h +17 -12
- data/ext/{apache2 → common}/Exceptions.h +17 -12
- data/ext/{apache2 → common}/FileChecker.h +17 -12
- data/ext/common/Logging.cpp +65 -0
- data/ext/{apache2 → common}/Logging.h +17 -12
- data/ext/{apache2 → common}/MessageChannel.h +17 -12
- data/ext/{apache2 → common}/PoolOptions.h +17 -12
- data/ext/{apache2 → common}/SpawnManager.h +17 -12
- data/ext/{apache2 → common}/StandardApplicationPool.h +17 -12
- data/ext/common/StaticString.h +147 -0
- data/ext/common/SystemTime.cpp +33 -0
- data/ext/{apache2 → common}/SystemTime.h +17 -12
- data/ext/{apache2 → common}/Utils.cpp +69 -12
- data/ext/{apache2 → common}/Utils.h +41 -12
- data/ext/nginx/Configuration.c +1091 -0
- data/ext/nginx/Configuration.h +71 -0
- data/ext/nginx/ContentHandler.c +1154 -0
- data/ext/nginx/ContentHandler.h +64 -0
- data/ext/nginx/HelperServer.cpp +857 -0
- data/ext/nginx/HttpStatusExtractor.h +161 -0
- data/ext/nginx/ScgiRequestParser.h +317 -0
- data/ext/nginx/StaticContentHandler.c +222 -0
- data/ext/nginx/StaticContentHandler.h +37 -0
- data/ext/nginx/config +41 -0
- data/ext/nginx/ngx_http_passenger_module.c +572 -0
- data/ext/nginx/ngx_http_passenger_module.h +72 -0
- data/ext/oxt/backtrace.cpp +8 -1
- data/ext/oxt/system_calls.cpp +40 -0
- data/ext/oxt/system_calls.hpp +14 -7
- data/ext/phusion_passenger/extconf.rb +17 -12
- data/ext/phusion_passenger/native_support.c +19 -12
- data/lib/phusion_passenger/abstract_installer.rb +196 -0
- data/lib/phusion_passenger/abstract_request_handler.rb +19 -24
- data/lib/phusion_passenger/abstract_server.rb +17 -12
- data/lib/phusion_passenger/abstract_server_collection.rb +17 -12
- data/lib/phusion_passenger/admin_tools.rb +23 -0
- data/lib/phusion_passenger/admin_tools/control_process.rb +39 -13
- data/lib/phusion_passenger/application.rb +17 -12
- data/lib/phusion_passenger/console_text_template.rb +17 -12
- data/lib/phusion_passenger/constants.rb +22 -11
- data/lib/phusion_passenger/dependencies.rb +47 -12
- data/lib/phusion_passenger/events.rb +17 -12
- data/lib/phusion_passenger/exceptions.rb +17 -12
- data/lib/phusion_passenger/html_template.rb +17 -12
- data/lib/phusion_passenger/message_channel.rb +17 -12
- data/lib/phusion_passenger/packaging.rb +39 -0
- data/lib/phusion_passenger/platform_info.rb +48 -22
- data/lib/phusion_passenger/rack/application_spawner.rb +22 -11
- data/lib/phusion_passenger/rack/request_handler.rb +21 -12
- data/lib/phusion_passenger/railz/application_spawner.rb +23 -23
- data/lib/phusion_passenger/railz/framework_spawner.rb +18 -14
- data/lib/phusion_passenger/railz/request_handler.rb +18 -11
- data/lib/phusion_passenger/simple_benchmarking.rb +17 -12
- data/lib/phusion_passenger/spawn_manager.rb +17 -20
- data/lib/phusion_passenger/templates/{apache_must_be_compiled_with_compatible_mpm.txt.erb → apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{apache2_config_snippets.txt.erb → apache2/config_snippets.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{deployment_example.txt.erb → apache2/deployment_example.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{no_write_permission_to_passenger_root.txt.erb → apache2/no_write_permission_to_passenger_root.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{possible_solutions_for_compilation_and_installation_problems.txt.erb → apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{run_installer_as_root.txt.erb → apache2/run_installer_as_root.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{welcome.txt.erb → apache2/welcome.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/nginx/ask_for_extra_configure_flags.txt.erb +8 -0
- data/lib/phusion_passenger/templates/nginx/cannot_write_to_dir.txt.erb +11 -0
- data/lib/phusion_passenger/templates/nginx/config_snippets.txt.erb +17 -0
- data/lib/phusion_passenger/templates/nginx/config_snippets_inserted.txt.erb +20 -0
- data/lib/phusion_passenger/templates/nginx/confirm_extra_configure_flags.txt.erb +5 -0
- data/lib/phusion_passenger/templates/nginx/deployment_example.txt.erb +22 -0
- data/lib/phusion_passenger/templates/nginx/pcre_could_not_be_downloaded.txt.erb +11 -0
- data/lib/phusion_passenger/templates/nginx/pcre_could_not_be_extracted.txt.erb +11 -0
- data/lib/phusion_passenger/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +11 -0
- data/lib/phusion_passenger/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +20 -0
- data/lib/phusion_passenger/templates/nginx/query_download_and_install.txt.erb +21 -0
- data/lib/phusion_passenger/templates/nginx/run_installer_as_root.txt.erb +8 -0
- data/lib/phusion_passenger/templates/nginx/welcome.txt.erb +15 -0
- data/lib/phusion_passenger/utils.rb +20 -15
- data/lib/phusion_passenger/wsgi/application_spawner.rb +18 -11
- data/lib/phusion_passenger/wsgi/request_handler.py +23 -0
- data/misc/copy_boost_headers.rb +23 -0
- data/misc/find_owner_pipe_leaks.rb +18 -11
- data/misc/rake/cplusplus.rb +18 -11
- data/misc/rake/extensions.rb +21 -14
- data/misc/render_error_pages.rb +18 -11
- data/test/ApplicationPoolServerTest.cpp +1 -3
- data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +1 -1
- data/test/CxxTestMain.cpp +19 -3
- data/test/HttpStatusExtractorTest.cpp +181 -0
- data/test/ScgiRequestParserTest.cpp +337 -0
- data/test/StaticStringTest.cpp +51 -0
- data/test/UtilsTest.cpp +32 -0
- data/test/config.yml.example +5 -0
- data/test/{integration_tests.rb → integration_tests/apache2_tests.rb} +7 -299
- data/test/integration_tests/hello_world_rack_spec.rb +36 -0
- data/test/integration_tests/hello_world_wsgi_spec.rb +41 -0
- data/test/integration_tests/mycook_spec.rb +192 -0
- data/test/integration_tests/nginx_tests.rb +98 -0
- data/test/ruby/rack/application_spawner_spec.rb +40 -0
- data/test/stub/nginx/koi-utf +109 -0
- data/test/stub/nginx/koi-win +103 -0
- data/test/stub/nginx/mime.types +70 -0
- data/test/stub/nginx/nginx.conf.erb +57 -0
- data/test/stub/nginx/win-utf +126 -0
- data/test/stub/rails_apps/mycook/app/controllers/uploads_controller.rb +4 -0
- data/test/stub/rails_apps/mycook/config/routes.rb +1 -1
- data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
- data/test/support/Support.h +40 -0
- data/test/support/nginx_controller.rb +98 -0
- data/test/support/test_helper.rb +79 -0
- metadata +1091 -1028
- data/benchmark/DummyRequestHandler.cpp +0 -101
- data/ext/apache2/Logging.cpp +0 -60
- data/ext/apache2/SystemTime.cpp +0 -28
@@ -0,0 +1,144 @@
|
|
1
|
+
Phusion Passenger provides a set of tools, which are useful for system analysis,
|
2
|
+
maintenance and troubleshooting.
|
3
|
+
|
4
|
+
|
5
|
+
=== Inspecting memory usage ===
|
6
|
+
|
7
|
+
Process inspection tools such as `ps` and `top` are useful, but they
|
8
|
+
link:http://groups.google.com/group/phusion-passenger/msg/1fd1c233456d3180[rarely show the correct memory usage].
|
9
|
+
The real memory usage is usually lower than what `ps` and `top` report.
|
10
|
+
|
11
|
+
There are many technical reasons why this is so, but an explanation is beyond
|
12
|
+
the scope of this Users Guide. We kindly refer the interested reader to
|
13
|
+
operating systems literature about 'virtual memory' and 'copy-on-write'.
|
14
|
+
|
15
|
+
The tool `passenger-memory-stats` allows one to easily analyze Phusion Passenger's
|
16
|
+
and Apache's real memory usage. For example:
|
17
|
+
|
18
|
+
-------------------------------------------------------
|
19
|
+
[bash@localhost root]# passenger-memory-stats
|
20
|
+
------------- Apache processes --------------.
|
21
|
+
PID PPID Threads VMSize Private Name
|
22
|
+
---------------------------------------------.
|
23
|
+
5947 1 9 90.6 MB 0.5 MB /usr/sbin/apache2 -k start
|
24
|
+
5948 5947 1 18.9 MB 0.7 MB /usr/sbin/fcgi-pm -k start
|
25
|
+
6029 5947 1 42.7 MB 0.5 MB /usr/sbin/apache2 -k start
|
26
|
+
6030 5947 1 42.7 MB 0.5 MB /usr/sbin/apache2 -k start
|
27
|
+
6031 5947 1 42.5 MB 0.3 MB /usr/sbin/apache2 -k start
|
28
|
+
6033 5947 1 42.5 MB 0.4 MB /usr/sbin/apache2 -k start
|
29
|
+
6034 5947 1 50.5 MB 0.4 MB /usr/sbin/apache2 -k start
|
30
|
+
23482 5947 1 82.6 MB 0.4 MB /usr/sbin/apache2 -k start
|
31
|
+
### Processes: 8
|
32
|
+
### Total private dirty RSS: 3.50 MB
|
33
|
+
|
34
|
+
--------- Passenger processes ---------.
|
35
|
+
PID Threads VMSize Private Name
|
36
|
+
---------------------------------------.
|
37
|
+
6026 1 10.9 MB 4.7 MB Passenger spawn server
|
38
|
+
23481 1 26.7 MB 3.0 MB Passenger FrameworkSpawner: 2.0.2
|
39
|
+
23791 1 26.8 MB 2.9 MB Passenger ApplicationSpawner: /var/www/projects/app1-foobar
|
40
|
+
23793 1 26.9 MB 17.1 MB Rails: /var/www/projects/app1-foobar
|
41
|
+
### Processes: 4
|
42
|
+
### Total private dirty RSS: 27.76 M
|
43
|
+
-------------------------------------------------------
|
44
|
+
|
45
|
+
The 'Private' or 'private dirty RSS' field shows the *real* memory usage of processes. Here,
|
46
|
+
we see that all the Apache worker processes only take less than 1 MB memory each.
|
47
|
+
This is a lot less than the 50 MB-ish memory usage as shown in the 'VMSize' column
|
48
|
+
(which is what a lot of people think is the real memory usage, but is actually not).
|
49
|
+
|
50
|
+
NOTE: Private dirty RSS reporting only works on Linux. Unfortunately other operating systems
|
51
|
+
don't provide facilities for determining processes' private dirty RSS. On non-Linux systems,
|
52
|
+
the Resident Set Size is reported instead.
|
53
|
+
|
54
|
+
|
55
|
+
=== Inspecting Phusion Passenger's internal status ===
|
56
|
+
|
57
|
+
One can inspect Phusion Passenger's internal status with the tool `passenger-status`.
|
58
|
+
This tool must typically be run as root. For example:
|
59
|
+
|
60
|
+
--------------------------------------------------
|
61
|
+
[bash@localhost root]# passenger-status
|
62
|
+
----------- General information -----------
|
63
|
+
max = 6
|
64
|
+
count = 1
|
65
|
+
active = 0
|
66
|
+
inactive = 1
|
67
|
+
|
68
|
+
----------- Domains -----------
|
69
|
+
/var/www/projects/app1-foobar:
|
70
|
+
PID: 9617 Sessions: 0 Processed: 7 Uptime: 2m 23s
|
71
|
+
--------------------------------------------------
|
72
|
+
|
73
|
+
The 'general information' section shows the following information:
|
74
|
+
|
75
|
+
max:: The maximum number of application instances that Phusion Passenger will
|
76
|
+
spawn. This equals the value given for <<PassengerMaxPoolSize,PassengerMaxPoolSize>> (Apache)
|
77
|
+
or <<PassengerMaxPoolSize,passenger_max_pool_size>> (Nginx).
|
78
|
+
count:: The number of application instances that are currently alive. This value
|
79
|
+
is always less than or equal to 'max'.
|
80
|
+
active:: The number of application instances that are currently processing
|
81
|
+
requests. This value is always less than or equal to 'count'.
|
82
|
+
inactive:: The number of application instances that are currently *not* processing
|
83
|
+
requests, i.e. are idle. Idle application instances will be shutdown after a while,
|
84
|
+
as can be specified with <<PassengerPoolIdleTime,PassengerPoolIdleTime (Apache)>>/<<PassengerPoolIdleTime,passenger_pool_idle_time (Nginx)>> (unless this
|
85
|
+
value is set to 0, in which case application instances are never shut down via idle
|
86
|
+
time). The value of 'inactive' equals `count - active`.
|
87
|
+
|
88
|
+
The 'domains' section shows, for each application directory, information about running
|
89
|
+
application instances:
|
90
|
+
|
91
|
+
Sessions:: Shows how many HTTP client are currently in the queue of that application
|
92
|
+
Instance, waiting to be processed.
|
93
|
+
Processed:: Indicates how many requests the instance has served until now. *Tip:* it's
|
94
|
+
possible to limit this number with the <<PassengerMaxRequests,PassengerMaxRequests>>
|
95
|
+
configuration directive.
|
96
|
+
Uptime:: Shows for how long the application instance has been running.
|
97
|
+
|
98
|
+
Since Phusion Passenger uses fair load balancing by default, the number of sessions for the
|
99
|
+
application instances should be fairly close to each other. For example, this is fairly
|
100
|
+
normal:
|
101
|
+
--------------------------------
|
102
|
+
PID: 4281 Sessions: 2 Processed: 7 Uptime: 5m 11s
|
103
|
+
PID: 4268 Sessions: 0 Processed: 5 Uptime: 4m 52s
|
104
|
+
PID: 4265 Sessions: 1 Processed: 6 Uptime: 5m 38s
|
105
|
+
PID: 4275 Sessions: 1 Processed: 7 Uptime: 3m 14s
|
106
|
+
--------------------------------
|
107
|
+
|
108
|
+
But if you see a "spike", i.e. an application instance has an unusually high number of
|
109
|
+
sessions compared to the others, then there might be a problem:
|
110
|
+
--------------------------------
|
111
|
+
PID: 4281 Sessions: 2 Processed: 7 Uptime: 5m 11s
|
112
|
+
PID: 17468 Sessions: 8 <-+ Processed: 2 Uptime: 4m 47s
|
113
|
+
PID: 4265 Sessions: 1 | Processed: 6 Uptime: 5m 38s
|
114
|
+
PID: 4275 Sessions: 1 | Processed: 7 Uptime: 3m 14s
|
115
|
+
|
|
116
|
+
+---- "spike"
|
117
|
+
--------------------------------
|
118
|
+
|
119
|
+
Possible reasons why spikes can occur:
|
120
|
+
|
121
|
+
. Your application is busy processing a request that takes a very long time.
|
122
|
+
If this is the case, then you might want to turn
|
123
|
+
<<PassengerUseGlobalQueue,global queuing>> on.
|
124
|
+
. Your application is frozen, i.e. has stopped responding. See
|
125
|
+
<<debugging_frozen,Debugging frozen applications>> for tips.
|
126
|
+
|
127
|
+
|
128
|
+
[[debugging_frozen]]
|
129
|
+
=== Debugging frozen applications ===
|
130
|
+
|
131
|
+
If one of your application instances is frozen (stopped responding), then you
|
132
|
+
can figure out where it is frozen by killing it with 'SIGABRT'. This will cause the
|
133
|
+
application to raise an exception, with a backtrace.
|
134
|
+
|
135
|
+
The exception (with full backtrace information) is normally logged into the Apache
|
136
|
+
error log. But if your application or if its web framework has its own exception logging
|
137
|
+
routines, then exceptions might be logged into the application's log files instead.
|
138
|
+
This is the case with Ruby on Rails. So if you kill a Ruby on Rails application with
|
139
|
+
'SIGABRT', please check the application's 'production.log' first (assuming that you're
|
140
|
+
running it in a 'production' environment). If you don't see a backtrace there, check
|
141
|
+
the Apache error log.
|
142
|
+
|
143
|
+
NOTE: It is safe to kill application instances, even in live environments. Phusion Passenger
|
144
|
+
will restart killed application instances, as if nothing bad happened.
|
@@ -0,0 +1,13 @@
|
|
1
|
+
== Appendix A: About this document ==
|
2
|
+
|
3
|
+
The text of this document is licensed under the
|
4
|
+
link:http://creativecommons.org/licenses/by-sa/3.0/[Creative Commons
|
5
|
+
Attribution-Share Alike 3.0 Unported License].
|
6
|
+
|
7
|
+
image:images/by_sa.png[link="http://creativecommons.org/licenses/by-sa/3.0/"]
|
8
|
+
|
9
|
+
Phusion Passenger is brought to you by link:http://www.phusion.nl/[Phusion].
|
10
|
+
|
11
|
+
image:images/phusion_banner.png[link="http://www.phusion.nl/"]
|
12
|
+
|
13
|
+
Phusion Passenger is a trademark of Hongli Lai & Ninh Bui.
|
@@ -0,0 +1,63 @@
|
|
1
|
+
== Appendix B: Terminology ==
|
2
|
+
|
3
|
+
[[application_root]]
|
4
|
+
=== Application root ===
|
5
|
+
The root directory of an application that's served by Phusion Passenger.
|
6
|
+
|
7
|
+
In case of Ruby on Rails applications, this is the directory that contains
|
8
|
+
'Rakefile', 'app/', 'config/', 'public/', etc. In other words, the directory
|
9
|
+
pointed to by `RAILS_ROOT`. For example, take the following directory structure:
|
10
|
+
|
11
|
+
-----------------------------------------
|
12
|
+
/apps/foo/ <------ This is the Rails application's application root!
|
13
|
+
|
|
14
|
+
+- app/
|
15
|
+
| |
|
16
|
+
| +- controllers/
|
17
|
+
| |
|
18
|
+
| +- models/
|
19
|
+
| |
|
20
|
+
| +- views/
|
21
|
+
|
|
22
|
+
+- config/
|
23
|
+
| |
|
24
|
+
| +- environment.rb
|
25
|
+
| |
|
26
|
+
| +- ...
|
27
|
+
|
|
28
|
+
+- public/
|
29
|
+
| |
|
30
|
+
| +- ...
|
31
|
+
|
|
32
|
+
+- ...
|
33
|
+
-----------------------------------------
|
34
|
+
|
35
|
+
In case of Rack applications, this is the directory that contains 'config.ru'.
|
36
|
+
For example, take the following directory structure:
|
37
|
+
|
38
|
+
-----------------------------------------
|
39
|
+
/apps/bar/ <----- This is the Rack application's application root!
|
40
|
+
|
|
41
|
+
+- public/
|
42
|
+
| |
|
43
|
+
| +- ...
|
44
|
+
|
|
45
|
+
+- config.ru
|
46
|
+
|
|
47
|
+
+- ...
|
48
|
+
-----------------------------------------
|
49
|
+
|
50
|
+
In case of Python (WSGI) applications, this is the directory that contains
|
51
|
+
'passenger_wsgi.py'. For example, take the following directory structure:
|
52
|
+
|
53
|
+
-----------------------------------------
|
54
|
+
/apps/baz/ <----- This is the WSGI application's application root!
|
55
|
+
|
|
56
|
+
+- public/
|
57
|
+
| |
|
58
|
+
| +- ...
|
59
|
+
|
|
60
|
+
+- passenger_wsgi.py
|
61
|
+
|
|
62
|
+
+- ...
|
63
|
+
-----------------------------------------
|
@@ -0,0 +1,304 @@
|
|
1
|
+
[[spawning_methods_explained]]
|
2
|
+
== Appendix C: Spawning methods explained ==
|
3
|
+
|
4
|
+
At its core, Phusion Passenger is an HTTP proxy and process manager. It spawns
|
5
|
+
Ruby on Rails/Rack/WSGI worker processes (which may also be referred to as
|
6
|
+
'backend processes'), and forwards incoming HTTP request to one of the worker
|
7
|
+
processes.
|
8
|
+
|
9
|
+
While this may sound simple, there's not just one way to spawn worker processes.
|
10
|
+
Let's go over the different spawning methods. For simplicity's sake, let's
|
11
|
+
assume that we're only talking about Ruby on Rails applications.
|
12
|
+
|
13
|
+
=== The most straightforward and traditional way: conservative spawning ===
|
14
|
+
|
15
|
+
Phusion Passenger could create a new Ruby process, which will then load the
|
16
|
+
Rails application along with the entire Rails framework. This process will then
|
17
|
+
enter an request handling main loop.
|
18
|
+
|
19
|
+
This is the most straightforward way to spawn worker processes. If you're
|
20
|
+
familiar with the Mongrel application server, then this approach is exactly
|
21
|
+
what mongrel_cluster performs: it creates N worker processes, each which loads
|
22
|
+
a full copy of the Rails application and the Rails framework in memory. The Thin
|
23
|
+
application server employs pretty much the same approach.
|
24
|
+
|
25
|
+
Note that Phusion Passenger's version of conservative spawning differs slightly
|
26
|
+
from mongrel_cluster. Mongrel_cluster creates entirely new Ruby processes. In
|
27
|
+
programmers jargon, mongrel_cluster creates new Ruby processes by forking the
|
28
|
+
current process and exec()-ing a new Ruby interpreter. Phusion Passenger on the
|
29
|
+
other hand creates processes that reuse the already loaded Ruby interpreter. In
|
30
|
+
programmers jargon, Phusion Passenger calls fork(), but not exec().
|
31
|
+
|
32
|
+
=== The smart spawning method ===
|
33
|
+
|
34
|
+
NOTE: Smart spawning is only available for Ruby on Rails applications, not for
|
35
|
+
Rack applications or WSGI applications.
|
36
|
+
|
37
|
+
While conservative spawning works well, it's not as efficient as it could be
|
38
|
+
because each worker process has its own private copy of the Rails application
|
39
|
+
as well as the Rails framework. This wastes memory as well as startup time.
|
40
|
+
|
41
|
+
image:images/conservative_spawning.png[Worker processes and conservative spawning] +
|
42
|
+
'Figure: Worker processes and conservative spawning. Each worker process has its
|
43
|
+
own private copy of the application code and Rails framework code.'
|
44
|
+
|
45
|
+
It is possible to make the different worker processes share the memory occupied
|
46
|
+
by application and Rails framework code, by utilizing so-called
|
47
|
+
copy-on-write semantics of the virtual memory system on modern operating
|
48
|
+
systems. As a side effect, the startup time is also reduced. This is technique
|
49
|
+
is exploited by Phusion Passenger's 'smart' and 'smart-lv2' spawn methods.
|
50
|
+
|
51
|
+
==== How it works ====
|
52
|
+
|
53
|
+
When the 'smart-lv2' spawn method is being used, Phusion Passenger will first
|
54
|
+
create a so-called 'ApplicationSpawner server' process. This process loads the
|
55
|
+
entire Rails application along with the Rails framework, by loading
|
56
|
+
'environment.rb'. Then, whenever Phusion Passenger needs a new worker process,
|
57
|
+
it will instruct the ApplicationSpawner server to do so. The ApplicationSpawner
|
58
|
+
server will create a worker new process
|
59
|
+
that reuses the already loaded Rails application/framework. Creating a worker
|
60
|
+
process through an already running ApplicationSpawner server is very fast, about
|
61
|
+
10 times faster than loading the Rails application/framework from scratch. If
|
62
|
+
the Ruby interpreter is copy-on-write friendly (that is, if you're running
|
63
|
+
<<reducing_memory_usage,Ruby Enterprise Edition>>) then all created worker
|
64
|
+
processes will share as much common
|
65
|
+
memory as possible. That is, they will all share the same application and Rails
|
66
|
+
framework code.
|
67
|
+
|
68
|
+
image:images/smart-lv2.png[] +
|
69
|
+
'Figure: Worker processes and the smart-lv2 spawn method. All worker processes,
|
70
|
+
as well as the ApplicationSpawner, share the same application code and Rails
|
71
|
+
framework code.'
|
72
|
+
|
73
|
+
The 'smart' spawn method goes even further, by caching the Rails framework in
|
74
|
+
another process called the 'FrameworkSpawner server'. This process only loads
|
75
|
+
the Rails framework, not the application. When a FrameworkSpawner server is
|
76
|
+
instructed to create a new worker process, it will create a new
|
77
|
+
ApplicationSpawner to which the instruction will be delegated. All those
|
78
|
+
ApplicationSpawner servers, as well as all worker processes created by those
|
79
|
+
ApplicationSpawner servers, will share the same Rails framework code.
|
80
|
+
|
81
|
+
The 'smart-lv2' method allows different worker processes that belong to the same
|
82
|
+
application to share memory. The 'smart' method allows different worker
|
83
|
+
processes - that happen to use the same Rails version - to share memory, even if
|
84
|
+
they don't belong to the same application.
|
85
|
+
|
86
|
+
Notes:
|
87
|
+
|
88
|
+
- Vendored Rails frameworks cannot be shared by different applications, even if
|
89
|
+
both vendored Rails frameworks are the same version. So for efficiency reasons
|
90
|
+
we don't recommend vendoring Rails.
|
91
|
+
- ApplicationSpawner and FrameworkSpawner servers have an idle timeout just
|
92
|
+
like worker processes. If an ApplicationSpawner/FrameworkSpawner server hasn't
|
93
|
+
been instructed to do anything for a while, it will be shutdown in order to
|
94
|
+
conserve memory. This idle timeout is configurable.
|
95
|
+
|
96
|
+
==== Summary of benefits ====
|
97
|
+
|
98
|
+
Suppose that Phusion Passenger needs a new worker process for an application
|
99
|
+
that uses Rails 2.2.1.
|
100
|
+
|
101
|
+
- If the 'smart-lv2' spawning method is used, and an ApplicationSpawner server
|
102
|
+
for this application is already running, then worker process creation time is
|
103
|
+
about 10 times faster than conservative spawning. This worker process will also
|
104
|
+
share application and Rails framework code memory with the ApplicationSpawner
|
105
|
+
server and the worker processes that had been spawned by this ApplicationSpawner
|
106
|
+
server.
|
107
|
+
- If the 'smart' spawning method is used, and a FrameworkSpawner server for
|
108
|
+
Rails 2.2.1 is already running, but no ApplicationSpawner server for this
|
109
|
+
application is running, then worker process creation time is about 2 times
|
110
|
+
faster than conservative spawning. If there is an ApplicationSpawner server
|
111
|
+
for this application running, then worker process creation time is about 10
|
112
|
+
times faster. This worker process will also share application and Rails
|
113
|
+
framework code memory with the ApplicationSpawner and FrameworkSpawner
|
114
|
+
servers.
|
115
|
+
|
116
|
+
You could compare ApplicationSpawner and FrameworkSpawner servers with stem
|
117
|
+
cells, that have the ability to quickly change into more specific cells (worker
|
118
|
+
process).
|
119
|
+
|
120
|
+
In practice, the smart spawning methods could mean a memory saving of about 33%,
|
121
|
+
assuming that your Ruby interpreter is <<reducing_memory_usage,copy-on-write friendly>>.
|
122
|
+
|
123
|
+
Of course, smart spawning is not without gotchas. But if you understand the
|
124
|
+
gotchas you can easily reap the benefits of smart spawning.
|
125
|
+
|
126
|
+
=== Smart spawning gotcha #1: unintential file descriptor sharing ===
|
127
|
+
|
128
|
+
Because worker processes are created by forking from an ApplicationSpawner
|
129
|
+
server, it will share all file descriptors that are opened by the
|
130
|
+
ApplicationSpawner server. (This is part of the semantics of the Unix
|
131
|
+
'fork()' system call. You might want to Google it if you're not familiar with
|
132
|
+
it.) A file descriptor is a handle which can be an opened file, an opened socket
|
133
|
+
connection, a pipe, etc. If different worker processes write to such a file
|
134
|
+
descriptor at the same time, then their write calls will be interleaved, which
|
135
|
+
may potentially cause problems.
|
136
|
+
|
137
|
+
The problem commonly involves socket connections that are unintentially being
|
138
|
+
shared. You can fix it by closing and reestablishing the connection when Phusion
|
139
|
+
Passenger is creating a new worker process. Phusion Passenger provides the API
|
140
|
+
call `PhusionPassenger.on_event(:starting_worker_process)` to do so. So you
|
141
|
+
could insert the following code in your 'environment.rb':
|
142
|
+
|
143
|
+
[source, ruby]
|
144
|
+
-----------------------------------------
|
145
|
+
if defined?(PhusionPassenger)
|
146
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
147
|
+
if forked
|
148
|
+
# We're in smart spawning mode.
|
149
|
+
... code to reestablish socket connections here ...
|
150
|
+
else
|
151
|
+
# We're in conservative spawning mode. We don't need to do anything.
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
-----------------------------------------
|
156
|
+
|
157
|
+
Note that Phusion Passenger automatically reestablishes the connection to the
|
158
|
+
database upon creating a new worker process, which is why you normally do not
|
159
|
+
encounter any database issues when using smart spawning mode.
|
160
|
+
|
161
|
+
==== Example 1: Memcached connection sharing (harmful) ====
|
162
|
+
|
163
|
+
Suppose we have a Rails application that connects to a Memcached server in
|
164
|
+
'environment.rb'. This causes the ApplicationSpawner to have a socket connection
|
165
|
+
(file descriptor) to the Memcached server, as shown in the following figure:
|
166
|
+
|
167
|
+
+--------------------+
|
168
|
+
| ApplicationSpawner |-----------[Memcached server]
|
169
|
+
+--------------------+
|
170
|
+
|
171
|
+
Phusion Passenger then proceeds with creating a new Rails worker process, which
|
172
|
+
is to process incoming HTTP requests. The result will look like this:
|
173
|
+
|
174
|
+
+--------------------+
|
175
|
+
| ApplicationSpawner |------+----[Memcached server]
|
176
|
+
+--------------------+ |
|
177
|
+
|
|
178
|
+
+--------------------+ |
|
179
|
+
| Worker process 1 |-----/
|
180
|
+
+--------------------+
|
181
|
+
|
182
|
+
Since a 'fork()' makes a (virtual) complete copy of a process, all its file
|
183
|
+
descriptors will be copied as well. What we see here is that ApplicationSpawner
|
184
|
+
and Worker process 1 both share the same connection to Memcached.
|
185
|
+
|
186
|
+
Now supposed that your site gets Slashdotted and Phusion Passenger needs to
|
187
|
+
spawn another worker process. It does so by forking ApplicationSpawner. The
|
188
|
+
result is now as follows:
|
189
|
+
|
190
|
+
+--------------------+
|
191
|
+
| ApplicationSpawner |------+----[Memcached server]
|
192
|
+
+--------------------+ |
|
193
|
+
|
|
194
|
+
+--------------------+ |
|
195
|
+
| Worker process 1 |-----/|
|
196
|
+
+--------------------+ |
|
197
|
+
|
|
198
|
+
+--------------------+ |
|
199
|
+
| Worker process 2 |-----/
|
200
|
+
+--------------------+
|
201
|
+
|
202
|
+
As you can see, Worker process 1 and Worker process 2 have the same Memcache
|
203
|
+
connection.
|
204
|
+
|
205
|
+
Suppose that users Joe and Jane visit your website at the same time. Joe's
|
206
|
+
request is handled by Worker process 1, and Jane's request is handled by Worker
|
207
|
+
process 2. Both worker processes want to fetch something from Memcached. Suppose
|
208
|
+
that in order to do that, both handlers need to send a "FETCH" command to Memcached.
|
209
|
+
|
210
|
+
But suppose that, after worker process 1 having only sent "FE", a context switch
|
211
|
+
occurs, and worker process 2 starts sending a "FETCH" command to Memcached as
|
212
|
+
well. If worker process 2 succeeds in sending only one bye, 'F', then Memcached
|
213
|
+
will receive a command which begins with "FEF", a command that it does not
|
214
|
+
recognize. In other words: the data from both handlers get interleaved. And thus
|
215
|
+
Memcached is forced to handle this as an error.
|
216
|
+
|
217
|
+
This problem can be solved by reestablishing the connection to Memcached after forking:
|
218
|
+
|
219
|
+
+--------------------+
|
220
|
+
| ApplicationSpawner |------+----[Memcached server]
|
221
|
+
+--------------------+ | |
|
222
|
+
| |
|
223
|
+
+--------------------+ | |
|
224
|
+
| Worker process 1 |-----/| |
|
225
|
+
+--------------------+ | | <--- created this
|
226
|
+
X | new
|
227
|
+
| connection
|
228
|
+
X <-- closed this |
|
229
|
+
+--------------------+ | old |
|
230
|
+
| Worker process 2 |-----/ connection |
|
231
|
+
+--------------------+ |
|
232
|
+
| |
|
233
|
+
+-------------------------------------+
|
234
|
+
|
235
|
+
Worker process 2 now has its own, separate communication channel with Memcached.
|
236
|
+
The code in 'environment.rb' looks like this:
|
237
|
+
|
238
|
+
[source, ruby]
|
239
|
+
-----------------------------------------
|
240
|
+
if defined?(PhusionPassenger)
|
241
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
242
|
+
if forked
|
243
|
+
# We're in smart spawning mode.
|
244
|
+
reestablish_connection_to_memcached
|
245
|
+
else
|
246
|
+
# We're in conservative spawning mode. We don't need to do anything.
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
-----------------------------------------
|
251
|
+
|
252
|
+
==== Example 2: Log file sharing (not harmful) ====
|
253
|
+
|
254
|
+
There are also cases in which unintential file descriptor sharing is not harmful.
|
255
|
+
One such case is log file file descriptor sharing. Even if two processes write
|
256
|
+
to the log file at the same time, the worst thing that can happen is that the
|
257
|
+
data in the log file is interleaved.
|
258
|
+
|
259
|
+
To guarantee that the data written to the log file is never interleaved, you
|
260
|
+
must synchronize write access via an inter-process synchronization mechanism,
|
261
|
+
such as file locks. Reopening the log file, like you would have done in the
|
262
|
+
Memcached example, doesn't help.
|
263
|
+
|
264
|
+
=== Smart spawning gotcha #2: the need to revive threads ===
|
265
|
+
|
266
|
+
Another part of the 'fork()' system call's semantics is the fact that threads
|
267
|
+
disappear after a fork call. So if you've created any threads in environment.rb,
|
268
|
+
then those threads will no longer be running in newly created worker process.
|
269
|
+
You need to revive them when a new worker process is created. Use the
|
270
|
+
`:starting_worker_process` event that Phusion Passenger provides, like this:
|
271
|
+
|
272
|
+
[source, ruby]
|
273
|
+
-----------------------------------------
|
274
|
+
if defined?(PhusionPassenger)
|
275
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
276
|
+
if forked
|
277
|
+
# We're in smart spawning mode.
|
278
|
+
... code to revive threads here ...
|
279
|
+
else
|
280
|
+
# We're in conservative spawning mode. We don't need to do anything.
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
-----------------------------------------
|
285
|
+
|
286
|
+
=== Smart spawning gotcha #3: code load order ===
|
287
|
+
|
288
|
+
This gotcha is only applicable to the 'smart' spawn method, not the 'smart-lv2'
|
289
|
+
spawn method.
|
290
|
+
|
291
|
+
If your application expects the Rails framework to be not loaded during the
|
292
|
+
beginning of 'environment.rb', then it can cause problems when an
|
293
|
+
ApplicationSpawner is created from a FrameworkSpawner, which already has the
|
294
|
+
Rails framework loaded. The most common case is when applications try to patch
|
295
|
+
Rails by dropping a modified file that has the same name as Rails's own file,
|
296
|
+
in a path that comes earlier in the Ruby search path.
|
297
|
+
|
298
|
+
For example, suppose that we have an application which has a patched version
|
299
|
+
of 'active_record/base.rb' located in 'RAILS_ROOT/lib/patches', and
|
300
|
+
'RAILS_ROOT/lib/patches' comes first in the Ruby load path. When conservative
|
301
|
+
spawning is used, the patched version of 'base.rb' is properly loaded. When
|
302
|
+
'smart' (not 'smart-lv2') spawning is used, the original 'base.rb' is used
|
303
|
+
because it was already loaded, so a subsequent `require "active_record/base"`
|
304
|
+
has no effect.
|