passenger 4.0.30 → 4.0.31
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data.tar.gz.asc +7 -7
- data/NEWS +31 -0
- data/bin/passenger +5 -5
- data/bin/passenger-config +6 -126
- data/bin/passenger-install-apache2-module +108 -26
- data/bin/passenger-install-nginx-module +81 -27
- data/bin/passenger-memory-stats +7 -6
- data/bin/passenger-status +13 -10
- data/build/agents.rb +8 -12
- data/build/apache2.rb +12 -7
- data/build/basics.rb +28 -20
- data/build/common_library.rb +4 -4
- data/build/cplusplus_support.rb +4 -4
- data/build/cxx_tests.rb +5 -3
- data/build/debian.rb +1 -2
- data/build/integration_tests.rb +25 -9
- data/build/misc.rb +2 -2
- data/build/oxt_tests.rb +5 -6
- data/build/packaging.rb +72 -40
- data/build/ruby_tests.rb +5 -1
- data/build/test_basics.rb +1 -2
- data/debian.template/locations.ini.template +1 -0
- data/debian.template/rules.template +2 -1
- data/dev/install_scripts_bootstrap_code.rb +42 -0
- data/dev/run_travis.sh +1 -0
- data/dev/runner +27 -0
- data/doc/Packaging.txt.md +5 -10
- data/doc/Users guide Apache.idmap.txt +3 -1
- data/doc/Users guide Apache.txt +5 -3
- data/doc/Users guide Nginx.idmap.txt +9 -5
- data/doc/Users guide Nginx.txt +47 -17
- data/doc/users_guide_snippets/environment_variables.txt +2 -2
- data/doc/users_guide_snippets/installation.txt +6 -2
- data/doc/users_guide_snippets/tips.txt +4 -0
- data/ext/apache2/Hooks.cpp +16 -3
- data/ext/common/Account.h +6 -5
- data/ext/common/AgentsStarter.h +1 -1
- data/ext/common/ApplicationPool2/Common.h +72 -0
- data/ext/common/ApplicationPool2/Group.h +263 -148
- data/ext/common/ApplicationPool2/Implementation.cpp +66 -44
- data/ext/common/ApplicationPool2/Options.h +1 -7
- data/ext/common/ApplicationPool2/Pool.h +96 -72
- data/ext/common/ApplicationPool2/Process.h +12 -17
- data/ext/common/ApplicationPool2/Socket.h +4 -4
- data/ext/common/ApplicationPool2/SuperGroup.h +20 -17
- data/ext/common/Constants.h +15 -1
- data/ext/common/MessageServer.h +22 -0
- data/ext/common/Utils.cpp +4 -1
- data/ext/common/Utils.h +3 -1
- data/ext/common/Utils/StrIntUtils.h +1 -0
- data/ext/common/Utils/Timer.h +15 -1
- data/ext/common/Utils/utf8/checked.h +0 -0
- data/ext/common/Utils/utf8/core.h +0 -0
- data/ext/common/Utils/utf8/unchecked.h +0 -0
- data/ext/common/agents/Base.cpp +59 -35
- data/ext/common/agents/HelperAgent/Main.cpp +23 -12
- data/ext/common/agents/HelperAgent/RequestHandler.h +10 -1
- data/ext/common/agents/LoggingAgent/FilterSupport.h +9 -5
- data/ext/common/agents/TempDirToucher.c +12 -3
- data/ext/common/agents/Watchdog/Main.cpp +8 -2
- data/ext/nginx/ConfigurationCommands.c +10 -0
- data/ext/nginx/ConfigurationFields.h +2 -0
- data/ext/nginx/ContentHandler.c +32 -19
- data/ext/nginx/CreateLocationConfig.c +5 -0
- data/ext/nginx/MergeLocationConfig.c +6 -0
- data/ext/nginx/config +13 -6
- data/ext/ruby/passenger_native_support.c +61 -2
- data/helper-scripts/classic-rails-loader.rb +9 -10
- data/helper-scripts/classic-rails-preloader.rb +10 -11
- data/helper-scripts/node-loader.js +3 -2
- data/helper-scripts/rack-loader.rb +8 -9
- data/helper-scripts/rack-preloader.rb +9 -10
- data/lib/phusion_passenger.rb +36 -7
- data/lib/phusion_passenger/abstract_installer.rb +16 -15
- data/lib/phusion_passenger/active_support3_extensions/init.rb +1 -1
- data/lib/phusion_passenger/admin_tools/memory_stats.rb +2 -2
- data/lib/phusion_passenger/admin_tools/server_instance.rb +5 -5
- data/lib/phusion_passenger/analytics_logger.rb +3 -3
- data/lib/phusion_passenger/classic_rails/thread_handler_extension.rb +1 -1
- data/lib/phusion_passenger/config.rb +125 -0
- data/lib/phusion_passenger/config/about_command.rb +183 -0
- data/lib/phusion_passenger/config/command.rb +57 -0
- data/lib/phusion_passenger/config/restart_app_command.rb +146 -0
- data/lib/phusion_passenger/config/utils.rb +108 -0
- data/lib/phusion_passenger/console_text_template.rb +2 -1
- data/lib/phusion_passenger/constants.rb +7 -2
- data/lib/phusion_passenger/loader_shared_helpers.rb +12 -21
- data/lib/phusion_passenger/message_client.rb +15 -4
- data/lib/phusion_passenger/native_support.rb +116 -98
- data/lib/phusion_passenger/nginx/config_options.rb +5 -0
- data/lib/phusion_passenger/platform_info.rb +1 -1
- data/lib/phusion_passenger/platform_info/apache.rb +9 -5
- data/lib/phusion_passenger/platform_info/apache_detector.rb +5 -6
- data/lib/phusion_passenger/platform_info/binary_compatibility.rb +3 -3
- data/lib/phusion_passenger/platform_info/compiler.rb +29 -11
- data/lib/phusion_passenger/platform_info/curl.rb +1 -1
- data/lib/phusion_passenger/platform_info/cxx_portability.rb +30 -16
- data/lib/phusion_passenger/platform_info/depcheck.rb +6 -6
- data/lib/phusion_passenger/platform_info/linux.rb +2 -2
- data/lib/phusion_passenger/platform_info/operating_system.rb +25 -5
- data/lib/phusion_passenger/platform_info/ruby.rb +7 -4
- data/lib/phusion_passenger/platform_info/zlib.rb +1 -1
- data/lib/phusion_passenger/plugin.rb +0 -1
- data/lib/phusion_passenger/preloader_shared_helpers.rb +1 -1
- data/lib/phusion_passenger/public_api.rb +1 -1
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
- data/lib/phusion_passenger/request_handler.rb +8 -9
- data/lib/phusion_passenger/request_handler/thread_handler.rb +21 -9
- data/lib/phusion_passenger/ruby_core_enhancements.rb +1 -1
- data/lib/phusion_passenger/standalone/app_finder.rb +2 -2
- data/lib/phusion_passenger/standalone/command.rb +10 -8
- data/lib/phusion_passenger/standalone/help_command.rb +1 -1
- data/lib/phusion_passenger/standalone/main.rb +3 -3
- data/lib/phusion_passenger/standalone/package_runtime_command.rb +2 -2
- data/lib/phusion_passenger/standalone/runtime_installer.rb +55 -13
- data/lib/phusion_passenger/standalone/runtime_locator.rb +3 -3
- data/lib/phusion_passenger/standalone/start_command.rb +6 -7
- data/lib/phusion_passenger/standalone/status_command.rb +1 -1
- data/lib/phusion_passenger/standalone/stop_command.rb +1 -1
- data/lib/phusion_passenger/standalone/utils.rb +1 -1
- data/lib/phusion_passenger/standalone/version_command.rb +2 -3
- data/lib/phusion_passenger/utils.rb +1 -1
- data/lib/phusion_passenger/utils/download.rb +1 -2
- data/lib/phusion_passenger/utils/file_system_watcher.rb +1 -1
- data/lib/phusion_passenger/utils/hosts_file_parser.rb +1 -1
- data/lib/phusion_passenger/utils/tee_input.rb +1 -1
- data/lib/phusion_passenger/utils/terminal_choice_menu.rb +217 -0
- data/lib/phusion_passenger/utils/unseekable_socket.rb +1 -1
- data/resources/templates/apache2/config_snippets.txt.erb +2 -3
- data/resources/templates/apache2/deployment_example.txt.erb +2 -2
- data/resources/templates/apache2/notify_apache_module_installed.txt.erb +3 -0
- data/resources/templates/nginx/config_snippets.txt.erb +1 -1
- data/resources/templates/nginx/deployment_example.txt.erb +2 -2
- data/resources/templates/nginx/nginx_module_sources_not_available.txt.erb +11 -5
- data/rpm/Vagrantfile +1 -0
- data/test/cxx/ApplicationPool2/PoolTest.cpp +224 -35
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +6 -6
- data/test/cxx/MessagePassingTest.cpp +1 -1
- data/test/cxx/RequestHandlerTest.cpp +26 -26
- data/test/integration_tests/apache2_tests.rb +162 -243
- data/test/integration_tests/native_packaging_spec.rb +10 -10
- data/test/integration_tests/nginx_tests.rb +87 -107
- data/test/integration_tests/shared/example_webapp_tests.rb +246 -0
- data/test/integration_tests/source_packaging_test.rb +2 -1
- data/test/integration_tests/standalone_tests.rb +34 -19
- data/test/ruby/admin_tools_spec.rb +4 -4
- data/test/ruby/analytics_logger_spec.rb +1 -1
- data/test/ruby/debug_logging_spec.rb +2 -2
- data/test/ruby/message_channel_spec.rb +1 -1
- data/test/ruby/request_handler_spec.rb +171 -64
- data/test/ruby/shared/loader_sharedspec.rb +5 -5
- data/test/ruby/shared/rails/analytics_logging_extensions_sharedspec.rb +2 -2
- data/test/ruby/spec_helper.rb +4 -4
- data/test/ruby/standalone/runtime_installer_spec.rb +1 -1
- data/test/ruby/standalone/runtime_locator_spec.rb +1 -1
- data/test/ruby/utils/file_system_watcher_spec.rb +1 -1
- data/test/ruby/utils/hosts_file_parser.rb +1 -1
- data/test/ruby/utils/unseekable_socket_spec.rb +1 -1
- data/test/ruby/utils_spec.rb +4 -4
- data/test/stub/apache2/httpd.conf.erb +5 -0
- data/test/stub/index.html +1 -0
- data/test/stub/rack/config.ru +80 -33
- data/test/stub/{rails_apps/1.2/empty/app/models → rack/public}/.gitignore +0 -0
- data/test/stub/{rails_apps/1.2/empty → rails2.3-mycook}/Rakefile +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/controllers/application_controller.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/controllers/recipes_controller.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/controllers/uploads_controller.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/controllers/welcome_controller.rb +0 -0
- data/test/stub/{rails_apps/1.2/empty → rails2.3-mycook}/app/helpers/application_helper.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/helpers/recipes_helper.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/helpers/test_helper.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/helpers/uploads_helper.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/helpers/welcome_helper.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/views/layouts/default.rhtml +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/views/recipes/create.rhtml +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/views/recipes/index.rhtml +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/views/recipes/new.rhtml +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/views/uploads/index.rhtml +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/views/uploads/new.html.erb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/views/welcome/cached.rhtml +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/app/views/welcome/index.rhtml +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/config/boot.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/config/database.yml +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/config/environment.rb +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/config/environments/development.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/config/environments/production.rb +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/config/initializers/inflections.rb +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/config/initializers/mime_types.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/config/routes.rb +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/log/useless.txt +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/public/.htaccess +0 -0
- data/test/stub/{rails_apps/1.2/empty → rails2.3-mycook}/public/404.html +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/public/422.html +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/public/500.html +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/public/dispatch.cgi +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/public/dispatch.fcgi +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/public/dispatch.rb +0 -0
- data/test/stub/{rails_apps/1.2/empty → rails2.3-mycook}/public/favicon.ico +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/public/images/angrywizard.gif +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/public/images/cookbook.gif +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/public/images/header.png +0 -0
- data/test/stub/{rails_apps/1.2/empty → rails2.3-mycook}/public/images/rails.png +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/public/robots.txt +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/public/uploads.html +0 -0
- data/test/stub/{rails_apps/1.2/empty/db → rails2.3-mycook/public/uploads}/.gitignore +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/public/welcome/cached.html +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/script/about +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/script/console +0 -0
- data/test/stub/{rails_apps/2.2/empty → rails2.3-mycook}/script/dbconsole +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/script/destroy +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/script/generate +0 -0
- data/test/stub/{rails_apps/1.2/empty → rails2.3-mycook}/script/performance/benchmarker +0 -0
- data/test/stub/{rails_apps/1.2/empty → rails2.3-mycook}/script/performance/profiler +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/script/performance/request +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/script/plugin +0 -0
- data/test/stub/{rails_apps/1.2/empty → rails2.3-mycook}/script/process/inspector +0 -0
- data/test/stub/{rails_apps/1.2/empty → rails2.3-mycook}/script/process/reaper +0 -0
- data/test/stub/{rails_apps/1.2/empty → rails2.3-mycook}/script/process/spawner +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/script/runner +0 -0
- data/test/stub/{rails_apps/2.0/empty → rails2.3-mycook}/script/server +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/sites/some.site/public/uploads.html +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/sites/some.site/public/welcome/cached.html +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/tmp/cache/useless.txt +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/tmp/pids/useless.txt +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/tmp/sessions/useless.txt +0 -0
- data/test/stub/{rails_apps/2.3/mycook → rails2.3-mycook}/tmp/sockets/useless.txt +0 -0
- data/test/stub/rails2.3/app/controllers/foo_controller.rb +1 -1
- data/test/stub/rails2.3/config/routes.rb +1 -2
- data/test/stub/wsgi/passenger_wsgi.py +47 -8
- data/test/stub/{rails_apps/1.2/empty/public/stylesheets → wsgi/public}/.gitignore +0 -0
- data/test/support/apache2_controller.rb +2 -2
- data/test/support/nginx_controller.rb +11 -5
- data/test/support/placebo-preloader.rb +2 -2
- data/test/support/test_helper.rb +26 -7
- metadata +78 -240
- metadata.gz.asc +7 -7
- data/debian.template/repack.sh +0 -42
- data/debian.template/watch +0 -3
- data/test/integration_tests/cgi_environment_spec.rb +0 -36
- data/test/integration_tests/hello_world_rack_spec.rb +0 -43
- data/test/integration_tests/hello_world_wsgi_spec.rb +0 -41
- data/test/integration_tests/mycook_spec.rb +0 -166
- data/test/stub/rack/public/rack.jpg +0 -0
- data/test/stub/rails_apps/1.2/empty/.gitignore +0 -3
- data/test/stub/rails_apps/1.2/empty/app/controllers/application.rb +0 -7
- data/test/stub/rails_apps/1.2/empty/config/boot.rb +0 -108
- data/test/stub/rails_apps/1.2/empty/config/database.yml +0 -31
- data/test/stub/rails_apps/1.2/empty/config/environment.rb +0 -66
- data/test/stub/rails_apps/1.2/empty/config/environments/development.rb +0 -21
- data/test/stub/rails_apps/1.2/empty/config/environments/production.rb +0 -18
- data/test/stub/rails_apps/1.2/empty/config/environments/staging.rb +0 -18
- data/test/stub/rails_apps/1.2/empty/config/environments/test.rb +0 -19
- data/test/stub/rails_apps/1.2/empty/config/routes.rb +0 -23
- data/test/stub/rails_apps/1.2/empty/doc/README_FOR_APP +0 -2
- data/test/stub/rails_apps/1.2/empty/public/.htaccess +0 -40
- data/test/stub/rails_apps/1.2/empty/public/500.html +0 -30
- data/test/stub/rails_apps/1.2/empty/public/dispatch.cgi +0 -10
- data/test/stub/rails_apps/1.2/empty/public/dispatch.fcgi +0 -24
- data/test/stub/rails_apps/1.2/empty/public/dispatch.rb +0 -10
- data/test/stub/rails_apps/1.2/empty/public/robots.txt +0 -1
- data/test/stub/rails_apps/1.2/empty/script/about +0 -3
- data/test/stub/rails_apps/1.2/empty/script/breakpointer +0 -3
- data/test/stub/rails_apps/1.2/empty/script/console +0 -3
- data/test/stub/rails_apps/1.2/empty/script/destroy +0 -3
- data/test/stub/rails_apps/1.2/empty/script/generate +0 -3
- data/test/stub/rails_apps/1.2/empty/script/plugin +0 -3
- data/test/stub/rails_apps/1.2/empty/script/runner +0 -3
- data/test/stub/rails_apps/1.2/empty/script/server +0 -3
- data/test/stub/rails_apps/1.2/empty/test/test_helper.rb +0 -28
- data/test/stub/rails_apps/2.0/empty/.gitignore +0 -3
- data/test/stub/rails_apps/2.0/empty/Rakefile +0 -10
- data/test/stub/rails_apps/2.0/empty/app/controllers/application.rb +0 -10
- data/test/stub/rails_apps/2.0/empty/app/helpers/application_helper.rb +0 -3
- data/test/stub/rails_apps/2.0/empty/app/models/.gitignore +0 -0
- data/test/stub/rails_apps/2.0/empty/config/boot.rb +0 -108
- data/test/stub/rails_apps/2.0/empty/config/database.yml +0 -31
- data/test/stub/rails_apps/2.0/empty/config/environment.rb +0 -59
- data/test/stub/rails_apps/2.0/empty/config/environments/production.rb +0 -18
- data/test/stub/rails_apps/2.0/empty/config/environments/staging.rb +0 -18
- data/test/stub/rails_apps/2.0/empty/config/environments/test.rb +0 -22
- data/test/stub/rails_apps/2.0/empty/config/routes.rb +0 -35
- data/test/stub/rails_apps/2.0/empty/db/.gitignore +0 -0
- data/test/stub/rails_apps/2.0/empty/doc/README_FOR_APP +0 -2
- data/test/stub/rails_apps/2.0/empty/public/.htaccess +0 -40
- data/test/stub/rails_apps/2.0/empty/public/404.html +0 -30
- data/test/stub/rails_apps/2.0/empty/public/dispatch.cgi +0 -10
- data/test/stub/rails_apps/2.0/empty/public/dispatch.fcgi +0 -24
- data/test/stub/rails_apps/2.0/empty/public/dispatch.rb +0 -10
- data/test/stub/rails_apps/2.0/empty/public/favicon.ico +0 -0
- data/test/stub/rails_apps/2.0/empty/public/images/rails.png +0 -0
- data/test/stub/rails_apps/2.0/empty/public/stylesheets/.gitignore +0 -0
- data/test/stub/rails_apps/2.0/empty/script/performance/benchmarker +0 -3
- data/test/stub/rails_apps/2.0/empty/script/performance/profiler +0 -3
- data/test/stub/rails_apps/2.0/empty/script/process/inspector +0 -3
- data/test/stub/rails_apps/2.0/empty/script/process/reaper +0 -3
- data/test/stub/rails_apps/2.0/empty/script/process/spawner +0 -3
- data/test/stub/rails_apps/2.0/empty/test/test_helper.rb +0 -38
- data/test/stub/rails_apps/2.2/empty/.gitignore +0 -3
- data/test/stub/rails_apps/2.2/empty/Rakefile +0 -10
- data/test/stub/rails_apps/2.2/empty/app/controllers/application.rb +0 -15
- data/test/stub/rails_apps/2.2/empty/app/helpers/application_helper.rb +0 -3
- data/test/stub/rails_apps/2.2/empty/app/models/.gitignore +0 -0
- data/test/stub/rails_apps/2.2/empty/config/boot.rb +0 -109
- data/test/stub/rails_apps/2.2/empty/config/database.yml +0 -31
- data/test/stub/rails_apps/2.2/empty/config/environment.rb +0 -75
- data/test/stub/rails_apps/2.2/empty/config/environments/development.rb +0 -17
- data/test/stub/rails_apps/2.2/empty/config/environments/production.rb +0 -24
- data/test/stub/rails_apps/2.2/empty/config/environments/staging.rb +0 -24
- data/test/stub/rails_apps/2.2/empty/config/environments/test.rb +0 -22
- data/test/stub/rails_apps/2.2/empty/config/initializers/inflections.rb +0 -10
- data/test/stub/rails_apps/2.2/empty/config/initializers/mime_types.rb +0 -5
- data/test/stub/rails_apps/2.2/empty/config/initializers/new_rails_defaults.rb +0 -17
- data/test/stub/rails_apps/2.2/empty/config/locales/en.yml +0 -5
- data/test/stub/rails_apps/2.2/empty/config/routes.rb +0 -43
- data/test/stub/rails_apps/2.2/empty/db/.gitignore +0 -0
- data/test/stub/rails_apps/2.2/empty/doc/README_FOR_APP +0 -5
- data/test/stub/rails_apps/2.2/empty/public/404.html +0 -30
- data/test/stub/rails_apps/2.2/empty/public/422.html +0 -30
- data/test/stub/rails_apps/2.2/empty/public/500.html +0 -33
- data/test/stub/rails_apps/2.2/empty/public/dispatch.cgi +0 -10
- data/test/stub/rails_apps/2.2/empty/public/dispatch.fcgi +0 -24
- data/test/stub/rails_apps/2.2/empty/public/dispatch.rb +0 -10
- data/test/stub/rails_apps/2.2/empty/public/favicon.ico +0 -0
- data/test/stub/rails_apps/2.2/empty/public/images/rails.png +0 -0
- data/test/stub/rails_apps/2.2/empty/public/robots.txt +0 -5
- data/test/stub/rails_apps/2.2/empty/public/stylesheets/.gitignore +0 -0
- data/test/stub/rails_apps/2.2/empty/script/about +0 -4
- data/test/stub/rails_apps/2.2/empty/script/console +0 -3
- data/test/stub/rails_apps/2.2/empty/script/destroy +0 -3
- data/test/stub/rails_apps/2.2/empty/script/generate +0 -3
- data/test/stub/rails_apps/2.2/empty/script/performance/benchmarker +0 -3
- data/test/stub/rails_apps/2.2/empty/script/performance/profiler +0 -3
- data/test/stub/rails_apps/2.2/empty/script/performance/request +0 -3
- data/test/stub/rails_apps/2.2/empty/script/plugin +0 -3
- data/test/stub/rails_apps/2.2/empty/script/process/inspector +0 -3
- data/test/stub/rails_apps/2.2/empty/script/process/reaper +0 -3
- data/test/stub/rails_apps/2.2/empty/script/process/spawner +0 -3
- data/test/stub/rails_apps/2.2/empty/script/runner +0 -3
- data/test/stub/rails_apps/2.2/empty/script/server +0 -3
- data/test/stub/rails_apps/2.2/empty/test/performance/browsing_test.rb +0 -9
- data/test/stub/rails_apps/2.2/empty/test/test_helper.rb +0 -38
- data/test/stub/rails_apps/2.3/empty/.gitignore +0 -3
- data/test/stub/rails_apps/2.3/empty/Rakefile +0 -10
- data/test/stub/rails_apps/2.3/empty/app/controllers/application_controller.rb +0 -10
- data/test/stub/rails_apps/2.3/empty/app/helpers/application_helper.rb +0 -3
- data/test/stub/rails_apps/2.3/empty/app/models/.gitignore +0 -0
- data/test/stub/rails_apps/2.3/empty/config/boot.rb +0 -110
- data/test/stub/rails_apps/2.3/empty/config/database.yml +0 -31
- data/test/stub/rails_apps/2.3/empty/config/environment.rb +0 -41
- data/test/stub/rails_apps/2.3/empty/config/environments/development.rb +0 -17
- data/test/stub/rails_apps/2.3/empty/config/environments/production.rb +0 -28
- data/test/stub/rails_apps/2.3/empty/config/environments/staging.rb +0 -28
- data/test/stub/rails_apps/2.3/empty/config/environments/test.rb +0 -28
- data/test/stub/rails_apps/2.3/empty/config/initializers/backtrace_silencers.rb +0 -7
- data/test/stub/rails_apps/2.3/empty/config/initializers/inflections.rb +0 -10
- data/test/stub/rails_apps/2.3/empty/config/initializers/mime_types.rb +0 -5
- data/test/stub/rails_apps/2.3/empty/config/initializers/new_rails_defaults.rb +0 -21
- data/test/stub/rails_apps/2.3/empty/config/initializers/session_store.rb +0 -15
- data/test/stub/rails_apps/2.3/empty/config/locales/en.yml +0 -5
- data/test/stub/rails_apps/2.3/empty/config/routes.rb +0 -43
- data/test/stub/rails_apps/2.3/empty/db/.gitignore +0 -0
- data/test/stub/rails_apps/2.3/empty/db/seeds.rb +0 -7
- data/test/stub/rails_apps/2.3/empty/doc/README_FOR_APP +0 -2
- data/test/stub/rails_apps/2.3/empty/public/404.html +0 -30
- data/test/stub/rails_apps/2.3/empty/public/422.html +0 -30
- data/test/stub/rails_apps/2.3/empty/public/500.html +0 -30
- data/test/stub/rails_apps/2.3/empty/public/favicon.ico +0 -0
- data/test/stub/rails_apps/2.3/empty/public/images/rails.png +0 -0
- data/test/stub/rails_apps/2.3/empty/public/robots.txt +0 -5
- data/test/stub/rails_apps/2.3/empty/public/stylesheets/.gitignore +0 -0
- data/test/stub/rails_apps/2.3/empty/script/about +0 -4
- data/test/stub/rails_apps/2.3/empty/script/console +0 -3
- data/test/stub/rails_apps/2.3/empty/script/dbconsole +0 -3
- data/test/stub/rails_apps/2.3/empty/script/destroy +0 -3
- data/test/stub/rails_apps/2.3/empty/script/generate +0 -3
- data/test/stub/rails_apps/2.3/empty/script/performance/benchmarker +0 -3
- data/test/stub/rails_apps/2.3/empty/script/performance/profiler +0 -3
- data/test/stub/rails_apps/2.3/empty/script/plugin +0 -3
- data/test/stub/rails_apps/2.3/empty/script/runner +0 -3
- data/test/stub/rails_apps/2.3/empty/script/server +0 -3
- data/test/stub/rails_apps/2.3/empty/test/performance/browsing_test.rb +0 -9
- data/test/stub/rails_apps/2.3/empty/test/test_helper.rb +0 -38
- data/test/stub/rails_apps/2.3/mycook/Rakefile +0 -10
- data/test/stub/rails_apps/2.3/mycook/app/helpers/application_helper.rb +0 -3
- data/test/stub/rails_apps/2.3/mycook/config/environments/development.rb +0 -18
- data/test/stub/rails_apps/2.3/mycook/config/initializers/inflections.rb +0 -10
- data/test/stub/rails_apps/2.3/mycook/config/initializers/mime_types.rb +0 -5
- data/test/stub/rails_apps/2.3/mycook/public/404.html +0 -30
- data/test/stub/rails_apps/2.3/mycook/public/422.html +0 -30
- data/test/stub/rails_apps/2.3/mycook/public/500.html +0 -30
- data/test/stub/rails_apps/2.3/mycook/public/favicon.ico +0 -0
- data/test/stub/rails_apps/2.3/mycook/public/images/rails.png +0 -0
- data/test/stub/rails_apps/2.3/mycook/public/robots.txt +0 -5
- data/test/stub/rails_apps/2.3/mycook/public/uploads/.gitignore +0 -0
- data/test/stub/rails_apps/2.3/mycook/script/about +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/console +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/dbconsole +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/destroy +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/generate +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/performance/benchmarker +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/performance/profiler +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/performance/request +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/plugin +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/process/inspector +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/process/reaper +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/process/spawner +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/runner +0 -3
- data/test/stub/rails_apps/2.3/mycook/script/server +0 -3
- data/test/stub/wsgi/public/wsgi-snake.jpg +0 -0
data/ext/common/Account.h
CHANGED
@@ -28,9 +28,9 @@
|
|
28
28
|
#include <string>
|
29
29
|
#include <vector>
|
30
30
|
#include <boost/shared_ptr.hpp>
|
31
|
-
#include
|
32
|
-
#include
|
33
|
-
#include
|
31
|
+
#include <StaticString.h>
|
32
|
+
#include <Exceptions.h>
|
33
|
+
#include <Utils/StrIntUtils.h>
|
34
34
|
|
35
35
|
namespace Passenger {
|
36
36
|
|
@@ -66,8 +66,9 @@ public:
|
|
66
66
|
CLEAR = 1 << 0,
|
67
67
|
DETACH = 1 << 1,
|
68
68
|
SET_PARAMETERS = 1 << 2,
|
69
|
-
|
70
|
-
|
69
|
+
RESTART = 1 << 3,
|
70
|
+
INSPECT_BASIC_INFO = 1 << 4,
|
71
|
+
INSPECT_SENSITIVE_INFO = 1 << 5,
|
71
72
|
|
72
73
|
// HelperAgent admin rights.
|
73
74
|
INSPECT_REQUESTS = 1 << 8,
|
data/ext/common/AgentsStarter.h
CHANGED
@@ -49,6 +49,63 @@ class Group;
|
|
49
49
|
class Process;
|
50
50
|
class Session;
|
51
51
|
|
52
|
+
/**
|
53
|
+
* The result of a Group::spawn() call.
|
54
|
+
*/
|
55
|
+
enum SpawnResult {
|
56
|
+
// The spawn request has been honored. One or more processes are now being spawned.
|
57
|
+
SR_OK,
|
58
|
+
|
59
|
+
// A previous spawn request is still in progress, so this spawn request has been
|
60
|
+
// ignored. Having said that, the desired result (increasing the number of processes
|
61
|
+
// by one, within imposed constraints) will still be achieved.
|
62
|
+
SR_IN_PROGRESS,
|
63
|
+
|
64
|
+
// A non-rolling restart is currently in progress, so the spawn request cannot
|
65
|
+
// be honored.
|
66
|
+
SR_ERR_RESTARTING,
|
67
|
+
|
68
|
+
// Unable to spawn a new process: the upper bound of the group process limits have
|
69
|
+
// already been reached.
|
70
|
+
// The group limit is checked before checking whether the pool is at full capacity,
|
71
|
+
// so if you get this result then it is possible that the pool is also at full
|
72
|
+
// capacity at the same time.
|
73
|
+
SR_ERR_GROUP_UPPER_LIMITS_REACHED,
|
74
|
+
|
75
|
+
// Unable to spawn a new process: the pool is at full capacity. Pool capacity is
|
76
|
+
// checked after checking the group upper bound limits, so if you get this result
|
77
|
+
// then it is guaranteed that the group upper bound limits have not been reached.
|
78
|
+
SR_ERR_POOL_AT_FULL_CAPACITY
|
79
|
+
};
|
80
|
+
|
81
|
+
/**
|
82
|
+
* The result of a Group::attach() call.
|
83
|
+
*/
|
84
|
+
enum AttachResult {
|
85
|
+
// Attaching succeeded.
|
86
|
+
AR_OK,
|
87
|
+
|
88
|
+
// Attaching failed: the upper bound of the group process limits have
|
89
|
+
// already been reached.
|
90
|
+
// The group limit is checked before checking whether the pool is at full capacity,
|
91
|
+
// so if you get this result then it is possible that the pool is also at full
|
92
|
+
// capacity at the same time.
|
93
|
+
AR_GROUP_UPPER_LIMITS_REACHED,
|
94
|
+
|
95
|
+
// Attaching failed: the pool is at full capacity. Pool capacity is
|
96
|
+
// checked after checking the group upper bound limits, so if you get this result
|
97
|
+
// then it is guaranteed that the group upper bound limits have not been reached.
|
98
|
+
AR_POOL_AT_FULL_CAPACITY,
|
99
|
+
|
100
|
+
// Attaching failed: another group is waiting for capacity, while this group is
|
101
|
+
// not waiting for capacity. You should throw away the current process and let the
|
102
|
+
// other group spawn, e.g. by calling `pool->possiblySpawnMoreProcessesForExistingGroups()`.
|
103
|
+
// This is checked after checking for the group upper bound limits and the pool
|
104
|
+
// capacity, so if you get this result then there is guaranteed to be capacity
|
105
|
+
// in the current group and in the pool.
|
106
|
+
AR_ANOTHER_GROUP_IS_WAITING_FOR_CAPACITY
|
107
|
+
};
|
108
|
+
|
52
109
|
/**
|
53
110
|
* The result of a Pool::disableProcess/Group::disable() call. Some values are only
|
54
111
|
* returned by the functions, some values are only passed to the Group::disable()
|
@@ -79,6 +136,21 @@ enum DisableResult {
|
|
79
136
|
DR_DEFERRED
|
80
137
|
};
|
81
138
|
|
139
|
+
/**
|
140
|
+
* Determines the behavior of Pool::restartGroupsByName() and Group::restart().
|
141
|
+
* Specifically, determines whether to perform a rolling restart or not.
|
142
|
+
*/
|
143
|
+
enum RestartMethod {
|
144
|
+
// Whether a rolling restart is performed, is determined by whether rolling restart
|
145
|
+
// was enabled in the web server configuration (i.e. whether group->options.rollingRestart
|
146
|
+
// is already true).
|
147
|
+
RM_DEFAULT,
|
148
|
+
// Perform a blocking restart. group->options.rollingRestart will not be changed.
|
149
|
+
RM_BLOCKING,
|
150
|
+
// Perform a rolling restart. group->options.rollingRestart will not be changed.
|
151
|
+
RM_ROLLING
|
152
|
+
};
|
153
|
+
|
82
154
|
typedef boost::shared_ptr<Pool> PoolPtr;
|
83
155
|
typedef boost::shared_ptr<SuperGroup> SuperGroupPtr;
|
84
156
|
typedef boost::shared_ptr<Group> GroupPtr;
|
@@ -93,9 +93,38 @@ private:
|
|
93
93
|
};
|
94
94
|
|
95
95
|
/**
|
96
|
-
* Protects `
|
96
|
+
* Protects `lifeStatus`.
|
97
97
|
*/
|
98
98
|
mutable boost::mutex lifetimeSyncher;
|
99
|
+
/**
|
100
|
+
* A Group object progresses through a life.
|
101
|
+
*
|
102
|
+
* Do not access directly, always use `isAlive()`/`getLifeStatus()` or
|
103
|
+
* through `lifetimeSyncher`.
|
104
|
+
*
|
105
|
+
* Invariant:
|
106
|
+
* if lifeStatus != ALIVE:
|
107
|
+
* enabledCount == 0
|
108
|
+
* disablingCount == 0
|
109
|
+
* disabledCount == 0
|
110
|
+
*/
|
111
|
+
enum LifeStatus {
|
112
|
+
/** Up and operational. */
|
113
|
+
ALIVE,
|
114
|
+
/** Being shut down. The containing SuperGroup has issued the shutdown()
|
115
|
+
* command, and this Group is now waiting for all detached processes to
|
116
|
+
* exit. You cannot call `get()`, `restart()` and other mutating methods
|
117
|
+
* anymore, and all threads created by this Group will exit as soon
|
118
|
+
* as possible.
|
119
|
+
*/
|
120
|
+
SHUTTING_DOWN,
|
121
|
+
/**
|
122
|
+
* Shut down complete. Object no longer usable. No Processes are referenced
|
123
|
+
* from this Group anymore.
|
124
|
+
*/
|
125
|
+
SHUT_DOWN
|
126
|
+
} lifeStatus;
|
127
|
+
|
99
128
|
/**
|
100
129
|
* A back reference to the containing SuperGroup. Should never
|
101
130
|
* be NULL because a SuperGroup should outlive all its containing
|
@@ -114,7 +143,19 @@ private:
|
|
114
143
|
*/
|
115
144
|
unsigned int restartsInitiated;
|
116
145
|
/**
|
117
|
-
*
|
146
|
+
* The number of processes that are being spawned right now.
|
147
|
+
*
|
148
|
+
* Invariant:
|
149
|
+
* if processesBeingSpawned > 0: m_spawning
|
150
|
+
*/
|
151
|
+
short processesBeingSpawned;
|
152
|
+
/**
|
153
|
+
* Whether the spawner thread is currently working. Note that even
|
154
|
+
* if it's working, it doesn't necessarily mean that processes are
|
155
|
+
* being spawned (i.e. that processesBeingSpawned > 0). After the
|
156
|
+
* thread is done spawning a process, it will attempt to attach
|
157
|
+
* the newly-spawned process to the group. During that time it's not
|
158
|
+
* technically spawning anything.
|
118
159
|
*/
|
119
160
|
bool m_spawning;
|
120
161
|
/** Whether a non-rolling restart is in progress (i.e. whether spawnThreadRealMain()
|
@@ -125,35 +166,9 @@ private:
|
|
125
166
|
* When rolling restarting is in progress, this flag is false.
|
126
167
|
*
|
127
168
|
* Invariant:
|
128
|
-
* if m_restarting:
|
169
|
+
* if m_restarting: processesBeingSpawned == 0
|
129
170
|
*/
|
130
171
|
bool m_restarting;
|
131
|
-
/**
|
132
|
-
* Do not access directly, always use `isAlive()`/`getLifeStatus()` or
|
133
|
-
* through `lifetimeSyncher`.
|
134
|
-
*
|
135
|
-
* Invariant:
|
136
|
-
* if lifeStatus != ALIVE:
|
137
|
-
* enabledCount == 0
|
138
|
-
* disablingCount == 0
|
139
|
-
* disabledCount == 0
|
140
|
-
*/
|
141
|
-
enum LifeStatus {
|
142
|
-
/** Up and operational. */
|
143
|
-
ALIVE,
|
144
|
-
/** Being shut down. The containing SuperGroup has issued the shutdown()
|
145
|
-
* command, and this Group is now waiting for all detached processes to
|
146
|
-
* exit. You cannot call `get()`, `restart()` and other mutating methods
|
147
|
-
* anymore, and all threads created by this Group will exit as soon
|
148
|
-
* as possible.
|
149
|
-
*/
|
150
|
-
SHUTTING_DOWN,
|
151
|
-
/**
|
152
|
-
* Shut down. Object no longer usable. No Processes are referenced from
|
153
|
-
* this Group anymore.
|
154
|
-
*/
|
155
|
-
SHUT_DOWN
|
156
|
-
} lifeStatus;
|
157
172
|
|
158
173
|
/** Contains the spawn loop thread and the restarter thread. */
|
159
174
|
dynamic_thread_group interruptableThreads;
|
@@ -197,13 +212,16 @@ private:
|
|
197
212
|
unsigned int restartsInitiated);
|
198
213
|
void spawnThreadRealMain(const SpawnerPtr &spawner, const Options &options,
|
199
214
|
unsigned int restartsInitiated);
|
200
|
-
void finalizeRestart(GroupPtr self, Options options,
|
201
|
-
unsigned int restartsInitiated,
|
215
|
+
void finalizeRestart(GroupPtr self, Options options, RestartMethod method,
|
216
|
+
SpawnerFactoryPtr spawnerFactory, unsigned int restartsInitiated,
|
217
|
+
vector<Callback> postLockActions);
|
202
218
|
void startCheckingDetachedProcesses(bool immediately);
|
203
219
|
void detachedProcessesCheckerMain(GroupPtr self);
|
204
220
|
void wakeUpGarbageCollector();
|
205
221
|
bool poolAtFullCapacity() const;
|
206
222
|
bool anotherGroupIsWaitingForCapacity() const;
|
223
|
+
boost::shared_ptr<Group> findOtherGroupWaitingForCapacity() const;
|
224
|
+
ProcessPtr poolForceFreeCapacity(const Group *exclude, vector<Callback> &postLockActions);
|
207
225
|
bool testOverflowRequestQueue() const;
|
208
226
|
const ResourceLocator &getResourceLocator() const;
|
209
227
|
void runAttachHooks(const ProcessPtr process) const;
|
@@ -217,21 +235,22 @@ private:
|
|
217
235
|
assert(disablingCount >= 0);
|
218
236
|
assert(disabledCount >= 0);
|
219
237
|
assert(enabledProcesses.empty() == (pqueue.top() == NULL));
|
220
|
-
assert(!( enabledCount == 0 && disablingCount > 0 ) ||
|
221
|
-
assert(!( !
|
238
|
+
assert(!( enabledCount == 0 && disablingCount > 0 ) || ( processesBeingSpawned > 0) );
|
239
|
+
assert(!( !m_spawning ) || ( enabledCount > 0 || disablingCount == 0 ));
|
222
240
|
|
223
241
|
assert((lifeStatus == ALIVE) == (spawner != NULL));
|
224
242
|
|
225
243
|
// Verify getWaitlist invariants.
|
226
244
|
assert(!( !getWaitlist.empty() ) || ( enabledProcesses.empty() || verifyNoRequestsOnGetWaitlistAreRoutable() ));
|
227
|
-
assert(!( enabledProcesses.empty() && !
|
228
|
-
assert(!( !getWaitlist.empty() ) || ( !enabledProcesses.empty() ||
|
245
|
+
assert(!( enabledProcesses.empty() && !m_spawning && !restarting() && !poolAtFullCapacity() ) || ( getWaitlist.empty() ));
|
246
|
+
assert(!( !getWaitlist.empty() ) || ( !enabledProcesses.empty() || m_spawning || restarting() || poolAtFullCapacity() ));
|
229
247
|
|
230
248
|
// Verify disableWaitlist invariants.
|
231
249
|
assert((int) disableWaitlist.size() >= disablingCount);
|
232
250
|
|
233
|
-
// Verify m_spawning and m_restarting.
|
234
|
-
assert(!(
|
251
|
+
// Verify processesBeingSpawned, m_spawning and m_restarting.
|
252
|
+
assert(!( processesBeingSpawned > 0 ) || ( m_spawning ));
|
253
|
+
assert(!( m_restarting ) || ( processesBeingSpawned == 0 ));
|
235
254
|
|
236
255
|
// Verify lifeStatus.
|
237
256
|
LifeStatus lifeStatus = getLifeStatus();
|
@@ -345,7 +364,7 @@ private:
|
|
345
364
|
}
|
346
365
|
|
347
366
|
/* Determines which process to route a get() action to. The returned process
|
348
|
-
* is guaranteed to be `canBeRoutedTo()`, i.e. not
|
367
|
+
* is guaranteed to be `canBeRoutedTo()`, i.e. not totally busy.
|
349
368
|
*
|
350
369
|
* A request is routed to an enabled processes, or if there are none,
|
351
370
|
* from a disabling process. The rationale is as follows:
|
@@ -376,7 +395,7 @@ private:
|
|
376
395
|
}
|
377
396
|
}
|
378
397
|
} else {
|
379
|
-
Process *process =
|
398
|
+
Process *process = findProcessWithLowestBusyness(disablingProcesses);
|
380
399
|
if (process->canBeRoutedTo()) {
|
381
400
|
return RouteResult(process);
|
382
401
|
} else {
|
@@ -395,7 +414,7 @@ private:
|
|
395
414
|
} else {
|
396
415
|
pqueue.erase(process->pqHandle);
|
397
416
|
}
|
398
|
-
process->pqHandle = pqueue.push(process, process->
|
417
|
+
process->pqHandle = pqueue.push(process, process->busyness());
|
399
418
|
}
|
400
419
|
return session;
|
401
420
|
}
|
@@ -425,12 +444,12 @@ private:
|
|
425
444
|
return NULL;
|
426
445
|
}
|
427
446
|
|
428
|
-
Process *
|
447
|
+
Process *findProcessWithLowestBusyness(const ProcessList &processes) const {
|
429
448
|
Process *result = NULL;
|
430
449
|
ProcessList::const_iterator it, end = processes.end();
|
431
450
|
for (it = processes.begin(); it != end; it++) {
|
432
451
|
Process *process = it->get();
|
433
|
-
if (result == NULL || process->
|
452
|
+
if (result == NULL || process->busyness() < result->busyness()) {
|
434
453
|
result = process;
|
435
454
|
}
|
436
455
|
}
|
@@ -478,7 +497,7 @@ private:
|
|
478
497
|
process->it = destination.last_iterator();
|
479
498
|
if (&destination == &enabledProcesses) {
|
480
499
|
process->enabled = Process::ENABLED;
|
481
|
-
process->pqHandle = pqueue.push(process.get(), process->
|
500
|
+
process->pqHandle = pqueue.push(process.get(), process->busyness());
|
482
501
|
enabledCount++;
|
483
502
|
} else if (&destination == &disablingProcesses) {
|
484
503
|
process->enabled = Process::DISABLING;
|
@@ -664,7 +683,7 @@ public:
|
|
664
683
|
* their numbers.
|
665
684
|
* These lists do not intersect. A process is in exactly 1 list.
|
666
685
|
*
|
667
|
-
* 'pqueue' orders all enabled processes according to
|
686
|
+
* 'pqueue' orders all enabled processes according to busyness() values,
|
668
687
|
* from small to large.
|
669
688
|
*
|
670
689
|
* Invariants:
|
@@ -678,14 +697,14 @@ public:
|
|
678
697
|
* enabledProcesses.empty() == (pqueue.top() == NULL)
|
679
698
|
*
|
680
699
|
* if (enabledCount == 0):
|
681
|
-
*
|
700
|
+
* processesBeingSpawned > 0 || restarting() || poolAtFullCapacity()
|
682
701
|
* if (enabledCount == 0) and (disablingCount > 0):
|
683
|
-
*
|
684
|
-
* if !
|
685
|
-
* (enabledCount > 0)
|
702
|
+
* processesBeingSpawned > 0
|
703
|
+
* if !m_spawning:
|
704
|
+
* (enabledCount > 0) || (disablingCount == 0)
|
686
705
|
*
|
687
|
-
* if pqueue.top().
|
688
|
-
* All enabled processes are
|
706
|
+
* if pqueue.top().isTotallyBusy():
|
707
|
+
* All enabled processes are totally busy.
|
689
708
|
*
|
690
709
|
* for all process in enabledProcesses:
|
691
710
|
* process.enabled == Process::ENABLED
|
@@ -741,7 +760,7 @@ public:
|
|
741
760
|
* The only reason why there are no enabled processes, while at the same time we're
|
742
761
|
* not spawning or waiting for pool capacity, is because there is nothing to do.
|
743
762
|
*
|
744
|
-
* if enabledProcesses.empty() && !
|
763
|
+
* if enabledProcesses.empty() && !m_spawning && !restarting() && !poolAtFullCapacity():
|
745
764
|
* getWaitlist is empty
|
746
765
|
*
|
747
766
|
* Equivalently:
|
@@ -750,7 +769,7 @@ public:
|
|
750
769
|
* unable to do that because of resource limits.
|
751
770
|
*
|
752
771
|
* if getWaitlist is non-empty:
|
753
|
-
* !enabledProcesses.empty() ||
|
772
|
+
* !enabledProcesses.empty() || m_spawning || restarting() || poolAtFullCapacity()
|
754
773
|
*/
|
755
774
|
deque<GetWaiter> getWaitlist;
|
756
775
|
/**
|
@@ -768,7 +787,12 @@ public:
|
|
768
787
|
* (lifeStatus == ALIVE) == (spawner != NULL)
|
769
788
|
*/
|
770
789
|
SpawnerPtr spawner;
|
771
|
-
|
790
|
+
|
791
|
+
|
792
|
+
/********************************************
|
793
|
+
* Constructors and destructors
|
794
|
+
********************************************/
|
795
|
+
|
772
796
|
Group(const SuperGroupPtr &superGroup, const Options &options, const ComponentInfo &info);
|
773
797
|
~Group();
|
774
798
|
|
@@ -799,7 +823,52 @@ public:
|
|
799
823
|
}
|
800
824
|
}
|
801
825
|
|
802
|
-
|
826
|
+
|
827
|
+
/********************************************
|
828
|
+
* Life time and back-reference methods
|
829
|
+
********************************************/
|
830
|
+
|
831
|
+
/**
|
832
|
+
* Thread-safe.
|
833
|
+
* @pre getLifeState() != SHUT_DOWN
|
834
|
+
* @post result != NULL
|
835
|
+
*/
|
836
|
+
SuperGroupPtr getSuperGroup() const {
|
837
|
+
return superGroup.lock();
|
838
|
+
}
|
839
|
+
|
840
|
+
void setSuperGroup(const SuperGroupPtr &superGroup) {
|
841
|
+
assert(this->superGroup.lock() == NULL);
|
842
|
+
this->superGroup = superGroup;
|
843
|
+
}
|
844
|
+
|
845
|
+
/**
|
846
|
+
* Thread-safe.
|
847
|
+
* @pre getLifeState() != SHUT_DOWN
|
848
|
+
* @post result != NULL
|
849
|
+
*/
|
850
|
+
PoolPtr getPool() const;
|
851
|
+
|
852
|
+
// Thread-safe.
|
853
|
+
bool isAlive() const {
|
854
|
+
boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
|
855
|
+
return lifeStatus == ALIVE;
|
856
|
+
}
|
857
|
+
|
858
|
+
// Thread-safe.
|
859
|
+
LifeStatus getLifeStatus() const {
|
860
|
+
boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
|
861
|
+
return lifeStatus;
|
862
|
+
}
|
863
|
+
|
864
|
+
|
865
|
+
/********************************************
|
866
|
+
* Core methods
|
867
|
+
********************************************/
|
868
|
+
|
869
|
+
SessionPtr get(const Options &newOptions, const GetCallback &callback,
|
870
|
+
vector<Callback> &postLockActions)
|
871
|
+
{
|
803
872
|
assert(isAlive());
|
804
873
|
|
805
874
|
if (OXT_LIKELY(!restarting())) {
|
@@ -809,7 +878,22 @@ public:
|
|
809
878
|
mergeOptions(newOptions);
|
810
879
|
}
|
811
880
|
if (OXT_UNLIKELY(!newOptions.noop && shouldSpawnForGetAction())) {
|
812
|
-
spawn
|
881
|
+
// If we're trying to spawn the first process for this group, and
|
882
|
+
// spawning failed because the pool is at full capacity, then we
|
883
|
+
// try to kill some random idle process in the pool and try again.
|
884
|
+
if (spawn() == SR_ERR_POOL_AT_FULL_CAPACITY && enabledCount == 0) {
|
885
|
+
P_INFO("Unable to spawn the the sole process for group " << name <<
|
886
|
+
" because the max pool size has been reached. Trying " <<
|
887
|
+
"to shutdown another idle process to free capacity...");
|
888
|
+
if (poolForceFreeCapacity(this, postLockActions) != NULL) {
|
889
|
+
SpawnResult result = spawn();
|
890
|
+
assert(result == SR_OK);
|
891
|
+
(void) result;
|
892
|
+
} else {
|
893
|
+
P_INFO("There are no processes right now that are eligible "
|
894
|
+
"for shutdown. Will try again later.");
|
895
|
+
}
|
896
|
+
}
|
813
897
|
}
|
814
898
|
}
|
815
899
|
|
@@ -831,19 +915,19 @@ public:
|
|
831
915
|
* then we generally want to use them, except:
|
832
916
|
* - When non-rolling restarting because those disabling processes
|
833
917
|
* are from the old version.
|
834
|
-
* - When all disabling processes are
|
918
|
+
* - When all disabling processes are totally busy.
|
835
919
|
*
|
836
920
|
* Whenever a disabling process cannot be used, call the callback
|
837
921
|
* after a process has been spawned or has failed to spawn, or
|
838
922
|
* when a disabling process becomes available.
|
839
923
|
*/
|
840
|
-
assert(
|
924
|
+
assert(m_spawning || restarting() || poolAtFullCapacity());
|
841
925
|
|
842
926
|
if (disablingCount > 0 && !restarting()) {
|
843
|
-
Process *process =
|
927
|
+
Process *process = findProcessWithLowestBusyness(
|
844
928
|
disablingProcesses);
|
845
929
|
assert(process != NULL);
|
846
|
-
if (!process->
|
930
|
+
if (!process->isTotallyBusy()) {
|
847
931
|
return newSession(process);
|
848
932
|
}
|
849
933
|
}
|
@@ -855,7 +939,7 @@ public:
|
|
855
939
|
} else {
|
856
940
|
RouteResult result = route(newOptions);
|
857
941
|
if (result.process == NULL) {
|
858
|
-
/* Looks like all processes are
|
942
|
+
/* Looks like all processes are totally busy.
|
859
943
|
* Wait until a new one has been spawned or until
|
860
944
|
* resources have become free.
|
861
945
|
*/
|
@@ -869,53 +953,33 @@ public:
|
|
869
953
|
}
|
870
954
|
}
|
871
955
|
}
|
872
|
-
|
873
|
-
/**
|
874
|
-
* Thread-safe.
|
875
|
-
* @pre getLifeState() != SHUT_DOWN
|
876
|
-
* @post result != NULL
|
877
|
-
*/
|
878
|
-
SuperGroupPtr getSuperGroup() const {
|
879
|
-
return superGroup.lock();
|
880
|
-
}
|
881
|
-
|
882
|
-
void setSuperGroup(const SuperGroupPtr &superGroup) {
|
883
|
-
assert(this->superGroup.lock() == NULL);
|
884
|
-
this->superGroup = superGroup;
|
885
|
-
}
|
886
|
-
|
887
|
-
/**
|
888
|
-
* Thread-safe.
|
889
|
-
* @pre getLifeState() != SHUT_DOWN
|
890
|
-
* @post result != NULL
|
891
|
-
*/
|
892
|
-
PoolPtr getPool() const;
|
893
|
-
|
894
|
-
// Thread-safe.
|
895
|
-
bool isAlive() const {
|
896
|
-
boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
|
897
|
-
return lifeStatus == ALIVE;
|
898
|
-
}
|
899
956
|
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
957
|
+
|
958
|
+
/********************************************
|
959
|
+
* State mutation methods
|
960
|
+
********************************************/
|
961
|
+
|
906
962
|
// Thread-safe, but only call outside the pool lock!
|
907
963
|
void requestOOBW(const ProcessPtr &process);
|
908
|
-
|
964
|
+
|
909
965
|
/**
|
910
966
|
* Attaches the given process to this Group and mark it as enabled. This
|
911
|
-
* function doesn't touch getWaitlist so be sure to fix its invariants
|
912
|
-
* afterwards if necessary.
|
967
|
+
* function doesn't touch `getWaitlist` so be sure to fix its invariants
|
968
|
+
* afterwards if necessary, e.g. by calling `assignSessionsToGetWaiters()`.
|
913
969
|
*/
|
914
|
-
|
970
|
+
AttachResult attach(const ProcessPtr &process, vector<Callback> &postLockActions) {
|
915
971
|
assert(process->getGroup() == NULL || process->getGroup().get() == this);
|
916
972
|
assert(process->isAlive());
|
917
973
|
assert(isAlive());
|
918
974
|
|
975
|
+
if (processUpperLimitsReached()) {
|
976
|
+
return AR_GROUP_UPPER_LIMITS_REACHED;
|
977
|
+
} else if (poolAtFullCapacity()) {
|
978
|
+
return AR_POOL_AT_FULL_CAPACITY;
|
979
|
+
} else if (!isWaitingForCapacity() && anotherGroupIsWaitingForCapacity()) {
|
980
|
+
return AR_ANOTHER_GROUP_IS_WAITING_FOR_CAPACITY;
|
981
|
+
}
|
982
|
+
|
919
983
|
process->setGroup(shared_from_this());
|
920
984
|
process->stickySessionId = generateStickySessionId();
|
921
985
|
P_DEBUG("Attaching process " << process->inspect());
|
@@ -953,6 +1017,8 @@ public:
|
|
953
1017
|
wakeUpGarbageCollector();
|
954
1018
|
|
955
1019
|
postLockActions.push_back(boost::bind(&Group::runAttachHooks, this, process));
|
1020
|
+
|
1021
|
+
return AR_OK;
|
956
1022
|
}
|
957
1023
|
|
958
1024
|
/**
|
@@ -1096,24 +1162,104 @@ public:
|
|
1096
1162
|
}
|
1097
1163
|
}
|
1098
1164
|
|
1165
|
+
/**
|
1166
|
+
* Attempts to increase the number of processes by one, while respecting the
|
1167
|
+
* resource limits. That is, this method will ensure that there are at least
|
1168
|
+
* `minProcesses` processes, but no more than `maxProcesses` processes, and no
|
1169
|
+
* more than `pool->max` processes in the entire pool.
|
1170
|
+
*/
|
1171
|
+
SpawnResult spawn() {
|
1172
|
+
assert(isAlive());
|
1173
|
+
if (m_spawning) {
|
1174
|
+
return SR_IN_PROGRESS;
|
1175
|
+
} else if (restarting()) {
|
1176
|
+
return SR_ERR_RESTARTING;
|
1177
|
+
} else if (processUpperLimitsReached()) {
|
1178
|
+
return SR_ERR_GROUP_UPPER_LIMITS_REACHED;
|
1179
|
+
} else if (poolAtFullCapacity()) {
|
1180
|
+
return SR_ERR_POOL_AT_FULL_CAPACITY;
|
1181
|
+
} else {
|
1182
|
+
P_DEBUG("Requested spawning of new process for group " << name);
|
1183
|
+
interruptableThreads.create_thread(
|
1184
|
+
boost::bind(&Group::spawnThreadMain,
|
1185
|
+
this, shared_from_this(), spawner,
|
1186
|
+
options.copyAndPersist().clearPerRequestFields(),
|
1187
|
+
restartsInitiated),
|
1188
|
+
"Group process spawner: " + name,
|
1189
|
+
POOL_HELPER_THREAD_STACK_SIZE);
|
1190
|
+
m_spawning = true;
|
1191
|
+
processesBeingSpawned++;
|
1192
|
+
return SR_OK;
|
1193
|
+
}
|
1194
|
+
}
|
1195
|
+
|
1099
1196
|
void cleanupSpawner(vector<Callback> &postLockActions) {
|
1100
1197
|
assert(isAlive());
|
1101
1198
|
postLockActions.push_back(boost::bind(doCleanupSpawner, spawner));
|
1102
1199
|
}
|
1103
1200
|
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1201
|
+
void restart(const Options &options, RestartMethod method = RM_DEFAULT);
|
1202
|
+
|
1203
|
+
|
1204
|
+
/********************************************
|
1205
|
+
* Queries
|
1206
|
+
********************************************/
|
1207
|
+
|
1208
|
+
unsigned int getProcessCount() const {
|
1209
|
+
return enabledCount + disablingCount + disabledCount;
|
1110
1210
|
}
|
1111
|
-
|
1211
|
+
|
1212
|
+
/**
|
1213
|
+
* Returns the number of processes in this group that should be part of the
|
1214
|
+
* ApplicationPool process limits calculations.
|
1215
|
+
*/
|
1216
|
+
unsigned int capacityUsed() const {
|
1217
|
+
return enabledCount + disablingCount + disabledCount + processesBeingSpawned;
|
1218
|
+
}
|
1219
|
+
|
1220
|
+
/**
|
1221
|
+
* Returns whether the lower bound of the group-specific process limits
|
1222
|
+
* have been satisfied. Note that even if the result is false, the pool limits
|
1223
|
+
* may not allow spawning, so you should check `pool->atFullCapacity()` too.
|
1224
|
+
*/
|
1225
|
+
bool processLowerLimitsSatisfied() const {
|
1226
|
+
return capacityUsed() >= options.minProcesses;
|
1227
|
+
}
|
1228
|
+
|
1229
|
+
/**
|
1230
|
+
* Returns whether the upper bound of the group-specific process limits have
|
1231
|
+
* been reached, or surpassed. Does not check whether pool limits have been
|
1232
|
+
* reached. Use `pool->atFullCapacity()` to check for that.
|
1233
|
+
*/
|
1234
|
+
bool processUpperLimitsReached() const {
|
1235
|
+
return options.maxProcesses != 0 && capacityUsed() >= options.maxProcesses;
|
1236
|
+
}
|
1237
|
+
|
1238
|
+
/**
|
1239
|
+
* Returns whether all enabled processes are totally busy. If so, another
|
1240
|
+
* process should be spawned, if allowed by the process limits.
|
1241
|
+
* Returns false if there are no enabled processes.
|
1242
|
+
*/
|
1243
|
+
bool allEnabledProcessesAreTotallyBusy() const {
|
1244
|
+
return enabledCount > 0 && pqueue.top()->isTotallyBusy();
|
1245
|
+
}
|
1246
|
+
|
1247
|
+
/**
|
1248
|
+
* Checks whether this group is waiting for capacity on the pool to
|
1249
|
+
* become available before it can continue processing requests.
|
1250
|
+
*/
|
1251
|
+
bool isWaitingForCapacity() const {
|
1252
|
+
return enabledProcesses.empty()
|
1253
|
+
&& processesBeingSpawned == 0
|
1254
|
+
&& !m_restarting
|
1255
|
+
&& !getWaitlist.empty();
|
1256
|
+
}
|
1257
|
+
|
1112
1258
|
bool garbageCollectable(unsigned long long now = 0) const {
|
1113
1259
|
/* if (now == 0) {
|
1114
1260
|
now = SystemTime::getUsec();
|
1115
1261
|
}
|
1116
|
-
return
|
1262
|
+
return busyness() == 0
|
1117
1263
|
&& getWaitlist.empty()
|
1118
1264
|
&& disabledProcesses.empty()
|
1119
1265
|
&& options.getMaxPreloaderIdleTime() != 0
|
@@ -1128,26 +1274,15 @@ public:
|
|
1128
1274
|
* specific case that another get action is to be performed.
|
1129
1275
|
*/
|
1130
1276
|
bool shouldSpawnForGetAction() const;
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
* isn't already happening and the group isn't being restarted.
|
1136
|
-
* Will ensure that at least options.minProcesses processes are spawned.
|
1277
|
+
|
1278
|
+
/**
|
1279
|
+
* Whether a new process is allowed to be spawned for this group,
|
1280
|
+
* i.e. whether the upper processes limits have not been reached.
|
1137
1281
|
*/
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
interruptableThreads.create_thread(
|
1143
|
-
boost::bind(&Group::spawnThreadMain,
|
1144
|
-
this, shared_from_this(), spawner,
|
1145
|
-
options.copyAndPersist().clearPerRequestFields(),
|
1146
|
-
restartsInitiated),
|
1147
|
-
"Group process spawner: " + name,
|
1148
|
-
POOL_HELPER_THREAD_STACK_SIZE);
|
1149
|
-
m_spawning = true;
|
1150
|
-
}
|
1282
|
+
bool allowSpawn() const {
|
1283
|
+
return isAlive()
|
1284
|
+
&& !processUpperLimitsReached()
|
1285
|
+
&& !poolAtFullCapacity();
|
1151
1286
|
}
|
1152
1287
|
|
1153
1288
|
bool needsRestart(const Options &options) {
|
@@ -1159,9 +1294,7 @@ public:
|
|
1159
1294
|
fileChangeChecker.changed(restartFile, options.statThrottleRate);
|
1160
1295
|
}
|
1161
1296
|
}
|
1162
|
-
|
1163
|
-
void restart(const Options &options);
|
1164
|
-
|
1297
|
+
|
1165
1298
|
bool spawning() const {
|
1166
1299
|
return m_spawning;
|
1167
1300
|
}
|
@@ -1170,25 +1303,6 @@ public:
|
|
1170
1303
|
return m_restarting;
|
1171
1304
|
}
|
1172
1305
|
|
1173
|
-
/**
|
1174
|
-
* Returns the number of processes in this group that should be part for the
|
1175
|
-
* MaxPoolSize constraint calculation.
|
1176
|
-
*/
|
1177
|
-
unsigned int getProcessCount() const {
|
1178
|
-
return enabledCount + disablingCount + disabledCount;
|
1179
|
-
}
|
1180
|
-
|
1181
|
-
/**
|
1182
|
-
* Checks whether this group is waiting for capacity on the pool to
|
1183
|
-
* become available before it can continue processing requests.
|
1184
|
-
*/
|
1185
|
-
bool isWaitingForCapacity() const {
|
1186
|
-
return enabledProcesses.empty()
|
1187
|
-
&& !m_spawning
|
1188
|
-
&& !m_restarting
|
1189
|
-
&& !getWaitlist.empty();
|
1190
|
-
}
|
1191
|
-
|
1192
1306
|
template<typename Stream>
|
1193
1307
|
void inspectXml(Stream &stream, bool includeSecrets = true) const {
|
1194
1308
|
ProcessList::const_iterator it;
|
@@ -1201,10 +1315,11 @@ public:
|
|
1201
1315
|
stream << "<enabled_process_count>" << enabledCount << "</enabled_process_count>";
|
1202
1316
|
stream << "<disabling_process_count>" << disablingCount << "</disabling_process_count>";
|
1203
1317
|
stream << "<disabled_process_count>" << disabledCount << "</disabled_process_count>";
|
1204
|
-
stream << "<
|
1318
|
+
stream << "<capacity_used>" << capacityUsed() << "</capacity_used>";
|
1205
1319
|
stream << "<get_wait_list_size>" << getWaitlist.size() << "</get_wait_list_size>";
|
1206
1320
|
stream << "<disable_wait_list_size>" << disableWaitlist.size() << "</disable_wait_list_size>";
|
1207
|
-
|
1321
|
+
stream << "<processes_being_spawned>" << processesBeingSpawned << "</processes_being_spawned>";
|
1322
|
+
if (m_spawning) {
|
1208
1323
|
stream << "<spawning/>";
|
1209
1324
|
}
|
1210
1325
|
if (restarting()) {
|