passenger 3.0.21 → 3.9.1.beta
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 +4 -10
- data/NEWS +19 -27
- data/Rakefile +20 -19
- data/bin/passenger +3 -2
- data/bin/passenger-config +35 -5
- data/bin/passenger-install-apache2-module +12 -12
- data/bin/passenger-install-nginx-module +55 -38
- data/bin/passenger-memory-stats +3 -1
- data/bin/passenger-status +7 -35
- data/build/agents.rb +107 -21
- data/build/apache2.rb +11 -46
- data/build/basics.rb +61 -9
- data/build/common_library.rb +59 -142
- data/build/cxx_tests.rb +111 -110
- data/build/documentation.rb +33 -0
- data/build/misc.rb +30 -12
- data/build/nginx.rb +10 -39
- data/build/oxt_tests.rb +1 -0
- data/build/ruby_extension.rb +1 -5
- data/build/test_basics.rb +3 -2
- data/dev/copy_boost_headers.rb +2 -1
- data/doc/Architectural overview.html +49 -90
- data/doc/DebuggingAndStressTesting.txt.md +49 -0
- data/doc/Packaging.txt.md +254 -0
- data/doc/Security of user switching support.html +35 -66
- data/doc/Users guide Apache.html +588 -758
- data/doc/Users guide Apache.idmap.txt +253 -136
- data/doc/Users guide Apache.txt +154 -109
- data/doc/Users guide Nginx.html +544 -660
- data/doc/Users guide Nginx.idmap.txt +179 -91
- data/doc/Users guide Nginx.txt +192 -118
- data/doc/Users guide Standalone.html +65 -48
- data/doc/Users guide Standalone.idmap.txt +10 -2
- data/doc/Users guide Standalone.txt +4 -0
- data/doc/images/glyphicons-halflings-white.png +0 -0
- data/doc/images/glyphicons-halflings.png +0 -0
- data/doc/images/phusion_banner_small.png +0 -0
- data/doc/images/{smart-lv2.png → smart.png} +0 -0
- data/doc/images/{smart-lv2.svg → smart.svg} +0 -0
- data/doc/templates/bootstrap.min.css +397 -0
- data/doc/templates/markdown.html.erb +117 -0
- data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +2 -1
- data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +26 -48
- data/doc/users_guide_snippets/passenger_spawn_method.txt +18 -30
- data/doc/users_guide_snippets/support_information.txt +30 -0
- data/ext/apache2/Bucket.cpp +9 -26
- data/ext/apache2/Bucket.h +13 -10
- data/ext/apache2/Configuration.cpp +70 -58
- data/ext/apache2/Configuration.hpp +19 -47
- data/ext/apache2/DirectoryMapper.h +7 -7
- data/ext/apache2/Hooks.cpp +150 -313
- data/ext/boost/algorithm/string/detail/case_conv.hpp +4 -2
- data/ext/boost/algorithm/string/detail/find_format.hpp +20 -20
- data/ext/boost/algorithm/string/detail/find_format_all.hpp +23 -23
- data/ext/boost/algorithm/string/detail/find_format_store.hpp +2 -2
- data/ext/boost/algorithm/string/detail/formatter.hpp +25 -0
- data/ext/boost/algorithm/string/formatter.hpp +20 -3
- data/ext/boost/assert.hpp +85 -4
- data/ext/boost/bind/bind.hpp +1 -1
- data/ext/boost/concept/detail/backward_compatibility.hpp +1 -1
- data/ext/boost/concept_check.hpp +140 -64
- data/ext/boost/config.hpp +1 -1
- data/ext/boost/config/auto_link.hpp +8 -6
- data/ext/boost/config/compiler/borland.hpp +12 -2
- data/ext/boost/config/compiler/clang.hpp +89 -30
- data/ext/boost/config/compiler/codegear.hpp +3 -2
- data/ext/boost/config/compiler/common_edg.hpp +7 -5
- data/ext/boost/config/compiler/cray.hpp +61 -0
- data/ext/boost/config/compiler/digitalmars.hpp +9 -1
- data/ext/boost/config/compiler/gcc.hpp +33 -24
- data/ext/boost/config/compiler/gcc_xml.hpp +4 -0
- data/ext/boost/config/compiler/hp_acc.hpp +12 -1
- data/ext/boost/config/compiler/intel.hpp +78 -4
- data/ext/boost/config/compiler/metrowerks.hpp +4 -1
- data/ext/boost/config/compiler/mpw.hpp +4 -1
- data/ext/boost/config/compiler/nvcc.hpp +8 -66
- data/ext/boost/config/compiler/pathscale.hpp +80 -0
- data/ext/boost/config/compiler/pgi.hpp +5 -5
- data/ext/boost/config/compiler/sunpro_cc.hpp +4 -1
- data/ext/boost/config/compiler/vacpp.hpp +37 -13
- data/ext/boost/config/compiler/visualc.hpp +24 -11
- data/ext/boost/config/platform/bsd.hpp +1 -1
- data/ext/boost/config/platform/cray.hpp +18 -0
- data/ext/boost/config/platform/cygwin.hpp +10 -0
- data/ext/boost/config/platform/linux.hpp +5 -0
- data/ext/boost/config/platform/macos.hpp +5 -4
- data/ext/boost/config/platform/symbian.hpp +5 -2
- data/ext/boost/config/platform/vms.hpp +25 -0
- data/ext/boost/config/platform/win32.hpp +7 -1
- data/ext/boost/config/select_compiler_config.hpp +8 -25
- data/ext/boost/config/select_platform_config.hpp +8 -1
- data/ext/boost/config/select_stdlib_config.hpp +9 -1
- data/ext/boost/config/stdlib/dinkumware.hpp +6 -9
- data/ext/boost/config/stdlib/libcomo.hpp +1 -4
- data/ext/boost/config/stdlib/libcpp.hpp +36 -0
- data/ext/boost/config/stdlib/libstdcpp3.hpp +37 -11
- data/ext/boost/config/stdlib/modena.hpp +1 -4
- data/ext/boost/config/stdlib/msl.hpp +1 -4
- data/ext/boost/config/stdlib/roguewave.hpp +9 -6
- data/ext/boost/config/stdlib/sgi.hpp +12 -4
- data/ext/boost/config/stdlib/stlport.hpp +11 -4
- data/ext/boost/config/stdlib/vacpp.hpp +11 -4
- data/ext/boost/config/suffix.hpp +71 -6
- data/ext/boost/config/warning_disable.hpp +1 -1
- data/ext/boost/container/container_fwd.hpp +177 -0
- data/ext/boost/cstdint.hpp +17 -12
- data/ext/boost/current_function.hpp +2 -1
- data/ext/boost/date_time/c_time.hpp +17 -1
- data/ext/boost/date_time/compiler_config.hpp +13 -15
- data/ext/boost/date_time/date_formatting.hpp +7 -1
- data/ext/boost/date_time/filetime_functions.hpp +4 -4
- data/ext/boost/date_time/gregorian_calendar.ipp +2 -2
- data/ext/boost/date_time/strings_from_facet.hpp +3 -3
- data/ext/boost/date_time/time_facet.hpp +101 -101
- data/ext/boost/detail/endian.hpp +4 -2
- data/ext/boost/detail/fenv.hpp +74 -0
- data/ext/boost/detail/sp_typeinfo.hpp +6 -0
- data/ext/boost/exception/detail/clone_current_exception.hpp +47 -0
- data/ext/boost/exception/detail/exception_ptr.hpp +194 -122
- data/ext/boost/exception/detail/type_info.hpp +3 -3
- data/ext/boost/exception/diagnostic_information.hpp +37 -21
- data/ext/boost/exception/exception.hpp +21 -1
- data/ext/boost/exception/info.hpp +0 -1
- data/ext/boost/function.hpp +2 -2
- data/ext/boost/function/function_base.hpp +15 -9
- data/ext/boost/function/function_template.hpp +26 -48
- data/ext/boost/integer_fwd.hpp +0 -16
- data/ext/boost/integer_traits.hpp +2 -2
- data/ext/boost/iterator.hpp +1 -1
- data/ext/boost/iterator/iterator_adaptor.hpp +1 -7
- data/ext/boost/iterator/iterator_facade.hpp +13 -13
- data/ext/boost/iterator/transform_iterator.hpp +5 -20
- data/ext/boost/lexical_cast.hpp +1655 -673
- data/ext/boost/math/policies/policy.hpp +982 -0
- data/ext/boost/math/special_functions/detail/fp_traits.hpp +570 -0
- data/ext/boost/math/special_functions/detail/round_fwd.hpp +80 -0
- data/ext/boost/math/special_functions/fpclassify.hpp +533 -0
- data/ext/boost/math/special_functions/math_fwd.hpp +1070 -0
- data/ext/boost/math/special_functions/sign.hpp +145 -0
- data/ext/boost/math/tools/config.hpp +321 -0
- data/ext/boost/math/tools/promotion.hpp +150 -0
- data/ext/boost/math/tools/real_cast.hpp +29 -0
- data/ext/boost/math/tools/user.hpp +97 -0
- data/ext/boost/move/move.hpp +1222 -0
- data/ext/boost/mpl/O1_size.hpp +40 -0
- data/ext/boost/mpl/O1_size_fwd.hpp +24 -0
- data/ext/boost/mpl/advance.hpp +76 -0
- data/ext/boost/mpl/advance_fwd.hpp +28 -0
- data/ext/boost/mpl/at.hpp +52 -0
- data/ext/boost/mpl/at_fwd.hpp +24 -0
- data/ext/boost/mpl/aux_/O1_size_impl.hpp +87 -0
- data/ext/boost/mpl/aux_/advance_backward.hpp +128 -0
- data/ext/boost/mpl/aux_/advance_forward.hpp +127 -0
- data/ext/boost/mpl/aux_/arithmetic_op.hpp +92 -0
- data/ext/boost/mpl/aux_/at_impl.hpp +45 -0
- data/ext/boost/mpl/aux_/begin_end_impl.hpp +101 -0
- data/ext/boost/mpl/aux_/clear_impl.hpp +35 -0
- data/ext/boost/mpl/aux_/comparison_op.hpp +83 -0
- data/ext/boost/mpl/aux_/config/forwarding.hpp +27 -0
- data/ext/boost/mpl/aux_/config/typeof.hpp +38 -0
- data/ext/boost/mpl/aux_/contains_impl.hpp +61 -0
- data/ext/boost/mpl/aux_/find_if_pred.hpp +31 -0
- data/ext/boost/mpl/aux_/fold_impl.hpp +43 -0
- data/ext/boost/mpl/aux_/has_begin.hpp +23 -0
- data/ext/boost/mpl/aux_/has_size.hpp +23 -0
- data/ext/boost/mpl/aux_/has_tag.hpp +23 -0
- data/ext/boost/mpl/aux_/inserter_algorithm.hpp +159 -0
- data/ext/boost/mpl/aux_/is_msvc_eti_arg.hpp +64 -0
- data/ext/boost/mpl/aux_/iter_apply.hpp +47 -0
- data/ext/boost/mpl/aux_/iter_fold_if_impl.hpp +210 -0
- data/ext/boost/mpl/aux_/iter_fold_impl.hpp +42 -0
- data/ext/boost/mpl/aux_/lambda_spec.hpp +49 -0
- data/ext/boost/mpl/aux_/largest_int.hpp +63 -0
- data/ext/boost/mpl/aux_/msvc_eti_base.hpp +77 -0
- data/ext/boost/mpl/aux_/msvc_type.hpp +62 -0
- data/ext/boost/mpl/aux_/numeric_cast_utils.hpp +77 -0
- data/ext/boost/mpl/aux_/numeric_op.hpp +315 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp +97 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp +97 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/equal_to.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp +180 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/greater.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/greater_equal.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp +133 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp +180 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/less.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/less_equal.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/list.hpp +323 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/minus.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/not_equal_to.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/plus.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp +231 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/times.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/vector.hpp +323 -0
- data/ext/boost/mpl/aux_/preprocessor/default_params.hpp +67 -0
- data/ext/boost/mpl/aux_/push_back_impl.hpp +70 -0
- data/ext/boost/mpl/aux_/push_front_impl.hpp +71 -0
- data/ext/boost/mpl/aux_/reverse_fold_impl.hpp +44 -0
- data/ext/boost/mpl/aux_/size_impl.hpp +52 -0
- data/ext/boost/mpl/aux_/traits_lambda_spec.hpp +63 -0
- data/ext/boost/mpl/back_fwd.hpp +24 -0
- data/ext/boost/mpl/back_inserter.hpp +34 -0
- data/ext/boost/mpl/begin_end.hpp +57 -0
- data/ext/boost/mpl/begin_end_fwd.hpp +27 -0
- data/ext/boost/mpl/clear.hpp +39 -0
- data/ext/boost/mpl/clear_fwd.hpp +24 -0
- data/ext/boost/mpl/comparison.hpp +24 -0
- data/ext/boost/mpl/contains.hpp +41 -0
- data/ext/boost/mpl/contains_fwd.hpp +25 -0
- data/ext/boost/mpl/deref.hpp +41 -0
- data/ext/boost/mpl/distance.hpp +78 -0
- data/ext/boost/mpl/distance_fwd.hpp +28 -0
- data/ext/boost/mpl/empty_fwd.hpp +24 -0
- data/ext/boost/mpl/equal_to.hpp +21 -0
- data/ext/boost/mpl/find.hpp +38 -0
- data/ext/boost/mpl/find_if.hpp +50 -0
- data/ext/boost/mpl/fold.hpp +48 -0
- data/ext/boost/mpl/front_fwd.hpp +24 -0
- data/ext/boost/mpl/front_inserter.hpp +33 -0
- data/ext/boost/mpl/greater.hpp +21 -0
- data/ext/boost/mpl/greater_equal.hpp +21 -0
- data/ext/boost/mpl/inserter.hpp +32 -0
- data/ext/boost/mpl/iter_fold.hpp +49 -0
- data/ext/boost/mpl/iter_fold_if.hpp +117 -0
- data/ext/boost/mpl/iterator_range.hpp +42 -0
- data/ext/boost/mpl/iterator_tags.hpp +27 -0
- data/ext/boost/mpl/less.hpp +21 -0
- data/ext/boost/mpl/less_equal.hpp +21 -0
- data/ext/boost/mpl/limits/list.hpp +21 -0
- data/ext/boost/mpl/limits/vector.hpp +21 -0
- data/ext/boost/mpl/list.hpp +57 -0
- data/ext/boost/mpl/list/aux_/O1_size.hpp +33 -0
- data/ext/boost/mpl/list/aux_/begin_end.hpp +44 -0
- data/ext/boost/mpl/list/aux_/clear.hpp +34 -0
- data/ext/boost/mpl/list/aux_/empty.hpp +34 -0
- data/ext/boost/mpl/list/aux_/front.hpp +33 -0
- data/ext/boost/mpl/list/aux_/include_preprocessed.hpp +35 -0
- data/ext/boost/mpl/list/aux_/item.hpp +55 -0
- data/ext/boost/mpl/list/aux_/iterator.hpp +76 -0
- data/ext/boost/mpl/list/aux_/pop_front.hpp +34 -0
- data/ext/boost/mpl/list/aux_/preprocessed/plain/list10.hpp +149 -0
- data/ext/boost/mpl/list/aux_/preprocessed/plain/list20.hpp +169 -0
- data/ext/boost/mpl/list/aux_/push_back.hpp +36 -0
- data/ext/boost/mpl/list/aux_/push_front.hpp +39 -0
- data/ext/boost/mpl/list/aux_/size.hpp +33 -0
- data/ext/boost/mpl/list/aux_/tag.hpp +24 -0
- data/ext/boost/mpl/list/list0.hpp +42 -0
- data/ext/boost/mpl/list/list10.hpp +43 -0
- data/ext/boost/mpl/list/list20.hpp +43 -0
- data/ext/boost/mpl/long.hpp +22 -0
- data/ext/boost/mpl/long_fwd.hpp +27 -0
- data/ext/boost/mpl/minus.hpp +21 -0
- data/ext/boost/mpl/multiplies.hpp +53 -0
- data/ext/boost/mpl/negate.hpp +81 -0
- data/ext/boost/mpl/not_equal_to.hpp +21 -0
- data/ext/boost/mpl/numeric_cast.hpp +41 -0
- data/ext/boost/mpl/pair.hpp +70 -0
- data/ext/boost/mpl/plus.hpp +21 -0
- data/ext/boost/mpl/pop_back_fwd.hpp +24 -0
- data/ext/boost/mpl/pop_front_fwd.hpp +24 -0
- data/ext/boost/mpl/prior.hpp +19 -0
- data/ext/boost/mpl/push_back.hpp +53 -0
- data/ext/boost/mpl/push_back_fwd.hpp +24 -0
- data/ext/boost/mpl/push_front.hpp +52 -0
- data/ext/boost/mpl/push_front_fwd.hpp +24 -0
- data/ext/boost/mpl/remove_if.hpp +83 -0
- data/ext/boost/mpl/reverse_fold.hpp +50 -0
- data/ext/boost/mpl/same_as.hpp +55 -0
- data/ext/boost/mpl/sequence_tag.hpp +124 -0
- data/ext/boost/mpl/sequence_tag_fwd.hpp +26 -0
- data/ext/boost/mpl/size.hpp +42 -0
- data/ext/boost/mpl/size_fwd.hpp +24 -0
- data/ext/boost/mpl/tag.hpp +52 -0
- data/ext/boost/mpl/times.hpp +21 -0
- data/ext/boost/mpl/vector.hpp +57 -0
- data/ext/boost/mpl/vector/aux_/O1_size.hpp +56 -0
- data/ext/boost/mpl/vector/aux_/at.hpp +116 -0
- data/ext/boost/mpl/vector/aux_/back.hpp +59 -0
- data/ext/boost/mpl/vector/aux_/begin_end.hpp +49 -0
- data/ext/boost/mpl/vector/aux_/clear.hpp +55 -0
- data/ext/boost/mpl/vector/aux_/empty.hpp +68 -0
- data/ext/boost/mpl/vector/aux_/front.hpp +56 -0
- data/ext/boost/mpl/vector/aux_/include_preprocessed.hpp +55 -0
- data/ext/boost/mpl/vector/aux_/item.hpp +103 -0
- data/ext/boost/mpl/vector/aux_/iterator.hpp +130 -0
- data/ext/boost/mpl/vector/aux_/pop_back.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/pop_front.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp +829 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp +1144 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp +139 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp +159 -0
- data/ext/boost/mpl/vector/aux_/push_back.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/push_front.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/size.hpp +49 -0
- data/ext/boost/mpl/vector/aux_/tag.hpp +32 -0
- data/ext/boost/mpl/vector/aux_/vector0.hpp +52 -0
- data/ext/boost/mpl/vector/vector0.hpp +34 -0
- data/ext/boost/mpl/vector/vector10.hpp +45 -0
- data/ext/boost/mpl/vector/vector20.hpp +45 -0
- data/ext/boost/none.hpp +1 -1
- data/ext/boost/numeric/conversion/bounds.hpp +24 -0
- data/ext/boost/numeric/conversion/cast.hpp +61 -0
- data/ext/boost/numeric/conversion/conversion_traits.hpp +39 -0
- data/ext/boost/numeric/conversion/converter.hpp +68 -0
- data/ext/boost/numeric/conversion/converter_policies.hpp +186 -0
- data/ext/boost/numeric/conversion/detail/bounds.hpp +58 -0
- data/ext/boost/numeric/conversion/detail/conversion_traits.hpp +97 -0
- data/ext/boost/numeric/conversion/detail/converter.hpp +602 -0
- data/ext/boost/numeric/conversion/detail/int_float_mixture.hpp +72 -0
- data/ext/boost/numeric/conversion/detail/is_subranged.hpp +234 -0
- data/ext/boost/numeric/conversion/detail/meta.hpp +120 -0
- data/ext/boost/numeric/conversion/detail/numeric_cast_traits.hpp +138 -0
- data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_common.hpp +1741 -0
- data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_long_long.hpp +347 -0
- data/ext/boost/numeric/conversion/detail/sign_mixture.hpp +72 -0
- data/ext/boost/numeric/conversion/detail/udt_builtin_mixture.hpp +69 -0
- data/ext/boost/numeric/conversion/int_float_mixture_enum.hpp +29 -0
- data/ext/boost/numeric/conversion/numeric_cast_traits.hpp +31 -0
- data/ext/boost/numeric/conversion/sign_mixture_enum.hpp +29 -0
- data/ext/boost/numeric/conversion/udt_builtin_mixture_enum.hpp +26 -0
- data/ext/boost/operators.hpp +3 -1
- data/ext/boost/optional/optional.hpp +146 -79
- data/ext/boost/optional/optional_fwd.hpp +8 -1
- data/ext/boost/preprocessor/cat.hpp +2 -2
- data/ext/boost/preprocessor/config/config.hpp +39 -4
- data/ext/boost/preprocessor/facilities/intercept.hpp +277 -0
- data/ext/boost/preprocessor/facilities/overload.hpp +25 -0
- data/ext/boost/preprocessor/iteration/detail/iter/forward1.hpp +3 -3
- data/ext/boost/preprocessor/iteration/iterate.hpp +3 -3
- data/ext/boost/preprocessor/punctuation/paren.hpp +23 -0
- data/ext/boost/preprocessor/repetition/enum_shifted_params.hpp +44 -0
- data/ext/boost/preprocessor/seq/cat.hpp +5 -4
- data/ext/boost/preprocessor/seq/size.hpp +0 -1
- data/ext/boost/preprocessor/tuple/eat.hpp +83 -34
- data/ext/boost/preprocessor/tuple/elem.hpp +161 -355
- data/ext/boost/preprocessor/tuple/rem.hpp +110 -48
- data/ext/boost/preprocessor/tuple/to_list.hpp +90 -36
- data/ext/boost/preprocessor/variadic/elem.hpp +94 -0
- data/ext/boost/preprocessor/variadic/size.hpp +30 -0
- data/ext/boost/range/begin.hpp +17 -6
- data/ext/boost/range/concepts.hpp +37 -2
- data/ext/boost/range/detail/safe_bool.hpp +72 -0
- data/ext/boost/range/end.hpp +14 -9
- data/ext/boost/range/iterator_range_core.hpp +120 -12
- data/ext/boost/range/size.hpp +21 -5
- data/ext/boost/smart_ptr/detail/shared_count.hpp +88 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base.hpp +3 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_aix.hpp +142 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +9 -0
- data/ext/boost/smart_ptr/detail/sp_counted_impl.hpp +10 -2
- data/ext/boost/smart_ptr/detail/sp_has_sync.hpp +5 -1
- data/ext/boost/smart_ptr/detail/spinlock.hpp +4 -1
- data/ext/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +20 -3
- data/ext/boost/smart_ptr/detail/spinlock_pool.hpp +4 -0
- data/ext/boost/smart_ptr/make_shared.hpp +591 -22
- data/ext/boost/smart_ptr/shared_array.hpp +29 -1
- data/ext/boost/smart_ptr/shared_ptr.hpp +29 -13
- data/ext/boost/smart_ptr/weak_ptr.hpp +24 -12
- data/ext/boost/src/pthread/once.cpp +9 -7
- data/ext/boost/src/pthread/thread.cpp +32 -28
- data/ext/boost/src/pthread/timeconv.inl +4 -5
- data/ext/boost/src/tss_null.cpp +5 -1
- data/ext/boost/static_assert.hpp +8 -2
- data/ext/boost/thread/detail/config.hpp +19 -4
- data/ext/boost/thread/detail/move.hpp +11 -5
- data/ext/boost/thread/detail/thread.hpp +59 -43
- data/ext/boost/thread/exceptions.hpp +9 -9
- data/ext/boost/thread/future.hpp +150 -82
- data/ext/boost/thread/locks.hpp +101 -60
- data/ext/boost/thread/pthread/condition_variable.hpp +79 -32
- data/ext/boost/thread/pthread/condition_variable_fwd.hpp +12 -3
- data/ext/boost/thread/pthread/mutex.hpp +17 -14
- data/ext/boost/thread/pthread/once.hpp +3 -4
- data/ext/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +12 -2
- data/ext/boost/thread/pthread/recursive_mutex.hpp +19 -19
- data/ext/boost/thread/pthread/shared_mutex.hpp +13 -13
- data/ext/boost/thread/pthread/thread_data.hpp +40 -12
- data/ext/boost/thread/thread_time.hpp +5 -0
- data/ext/boost/throw_exception.hpp +1 -1
- data/ext/boost/token_functions.hpp +34 -10
- data/ext/boost/type_traits/add_rvalue_reference.hpp +66 -0
- data/ext/boost/type_traits/alignment_of.hpp +1 -1
- data/ext/boost/type_traits/detail/bool_trait_def.hpp +26 -3
- data/ext/boost/type_traits/detail/bool_trait_undef.hpp +3 -2
- data/ext/boost/type_traits/detail/cv_traits_impl.hpp +1 -1
- data/ext/boost/type_traits/detail/size_t_trait_def.hpp +6 -4
- data/ext/boost/type_traits/detail/type_trait_def.hpp +8 -2
- data/ext/boost/type_traits/function_traits.hpp +1 -1
- data/ext/boost/type_traits/has_nothrow_constructor.hpp +53 -0
- data/ext/boost/type_traits/has_nothrow_copy.hpp +19 -5
- data/ext/boost/type_traits/has_trivial_constructor.hpp +51 -0
- data/ext/boost/type_traits/has_trivial_copy.hpp +20 -5
- data/ext/boost/type_traits/has_trivial_destructor.hpp +12 -5
- data/ext/boost/type_traits/intrinsics.hpp +119 -71
- data/ext/boost/type_traits/is_const.hpp +5 -5
- data/ext/boost/type_traits/is_convertible.hpp +14 -13
- data/ext/boost/type_traits/is_enum.hpp +1 -1
- data/ext/boost/type_traits/is_floating_point.hpp +27 -0
- data/ext/boost/type_traits/is_function.hpp +3 -3
- data/ext/boost/type_traits/is_fundamental.hpp +1 -1
- data/ext/boost/type_traits/is_member_function_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_member_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_pod.hpp +11 -3
- data/ext/boost/type_traits/is_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_signed.hpp +8 -3
- data/ext/boost/type_traits/is_union.hpp +8 -0
- data/ext/boost/type_traits/is_unsigned.hpp +9 -4
- data/ext/boost/type_traits/is_volatile.hpp +5 -5
- data/ext/boost/type_traits/remove_cv.hpp +4 -3
- data/ext/boost/type_traits/remove_pointer.hpp +51 -2
- data/ext/boost/type_traits/remove_reference.hpp +2 -2
- data/ext/boost/type_traits/type_with_alignment.hpp +8 -2
- data/ext/boost/utility/declval.hpp +44 -0
- data/ext/boost/utility/detail/in_place_factory_prefix.hpp +36 -0
- data/ext/boost/utility/detail/in_place_factory_suffix.hpp +23 -0
- data/ext/boost/utility/detail/result_of_iterate.hpp +142 -0
- data/ext/boost/utility/in_place_factory.hpp +88 -0
- data/ext/boost/utility/result_of.hpp +103 -0
- data/ext/boost/utility/swap.hpp +55 -0
- data/ext/common/AnsiColorConstants.h +36 -0
- data/ext/common/ApplicationPool2/Common.h +87 -0
- data/ext/common/ApplicationPool2/ComponentInfo.h +53 -0
- data/ext/common/ApplicationPool2/Group.h +648 -0
- data/ext/common/ApplicationPool2/Implementation.cpp +580 -0
- data/ext/common/ApplicationPool2/Options.h +576 -0
- data/ext/common/ApplicationPool2/PipeWatcher.h +61 -0
- data/ext/common/ApplicationPool2/Pool.h +1181 -0
- data/ext/common/ApplicationPool2/Process.h +425 -0
- data/ext/common/ApplicationPool2/README.md +96 -0
- data/ext/common/ApplicationPool2/Session.h +158 -0
- data/ext/common/ApplicationPool2/Socket.h +246 -0
- data/ext/common/ApplicationPool2/Spawner.h +2212 -0
- data/ext/common/ApplicationPool2/SuperGroup.h +749 -0
- data/ext/common/BackgroundEventLoop.cpp +129 -0
- data/ext/common/BackgroundEventLoop.h +61 -0
- data/ext/common/Constants.h +3 -1
- data/ext/common/EventedBufferedInput.h +331 -0
- data/ext/common/EventedMessageServer.h +17 -34
- data/ext/common/EventedServer.h +2 -2
- data/ext/common/Exceptions.h +71 -19
- data/ext/common/FileDescriptor.h +8 -6
- data/ext/common/HttpConstants.h +167 -0
- data/ext/common/IniFile.h +24 -0
- data/ext/common/Logging.h +62 -849
- data/ext/common/MessageReadersWriters.h +19 -0
- data/ext/common/MessageServer.h +11 -14
- data/ext/common/MultiLibeio.cpp +198 -0
- data/ext/common/MultiLibeio.h +67 -0
- data/ext/common/ResourceLocator.h +24 -41
- data/ext/common/SafeLibev.h +186 -14
- data/ext/common/StaticString.h +23 -3
- data/ext/common/UnionStation.h +972 -0
- data/ext/common/Utils.cpp +168 -24
- data/ext/common/Utils.h +25 -3
- data/ext/common/Utils/CachedFileStat.hpp +4 -3
- data/ext/common/Utils/FileChangeChecker.h +2 -2
- data/ext/common/Utils/HashMap.h +50 -0
- data/ext/common/Utils/IOUtils.cpp +229 -68
- data/ext/common/Utils/IOUtils.h +134 -3
- data/ext/common/Utils/Lock.h +28 -0
- data/ext/common/Utils/MemoryBarrier.h +52 -0
- data/ext/common/Utils/PriorityQueue.h +54 -0
- data/ext/common/Utils/ProcessMetricsCollector.h +9 -11
- data/ext/common/Utils/ScopeGuard.h +50 -1
- data/ext/common/Utils/SmallVector.h +653 -0
- data/ext/common/Utils/StrIntUtils.cpp +26 -2
- data/ext/common/Utils/StrIntUtils.h +18 -2
- data/ext/common/Utils/StringMap.h +125 -8
- data/ext/common/Utils/Template.h +212 -0
- data/ext/common/Utils/fib.c +699 -0
- data/ext/common/Utils/fib.h +101 -0
- data/ext/common/Utils/fibpriv.h +67 -0
- data/ext/common/Utils/json-forwards.h +249 -0
- data/ext/common/Utils/json.h +1855 -0
- data/ext/common/Utils/jsoncpp.cpp +4230 -0
- data/ext/common/agents/Base.cpp +1126 -0
- data/ext/common/{AgentBase.h → agents/Base.h} +5 -1
- data/ext/common/agents/EnvPrinter.c +16 -0
- data/ext/common/agents/HelperAgent/AgentOptions.h +81 -0
- data/ext/common/{HelperAgent → agents/HelperAgent}/BacktracesServer.h +3 -2
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +732 -0
- data/ext/common/agents/HelperAgent/Main.cpp +497 -0
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +283 -0
- data/ext/common/agents/HelperAgent/RequestHandler.h +2139 -0
- data/ext/common/agents/HelperAgent/ScgiRequestParser.h +451 -0
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/DataStoreId.h +1 -1
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.cpp +1 -1
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.h +0 -0
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/LoggingServer.h +18 -16
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/Main.cpp +15 -13
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/RemoteSender.h +6 -6
- data/ext/common/agents/SpawnPreparer.cpp +127 -0
- data/ext/common/{Watchdog.cpp → agents/Watchdog/Main.cpp} +63 -25
- data/ext/libeio/Changes +72 -0
- data/ext/{google/COPYING → libeio/LICENSE} +17 -9
- data/ext/libeio/Makefile.am +15 -0
- data/ext/libeio/Makefile.in +694 -0
- data/ext/libeio/aclocal.m4 +9418 -0
- data/ext/libeio/autogen.sh +3 -0
- data/ext/libeio/config.guess +1501 -0
- data/ext/libeio/config.h.in +136 -0
- data/ext/libeio/config.sub +1705 -0
- data/ext/libeio/configure +14822 -0
- data/ext/libeio/configure.ac +22 -0
- data/ext/libeio/demo.c +194 -0
- data/ext/libeio/ecb.h +457 -0
- data/ext/libeio/eio.c +2816 -0
- data/ext/libeio/eio.h +411 -0
- data/ext/libeio/install-sh +520 -0
- data/ext/libeio/libeio.m4 +211 -0
- data/ext/libeio/ltmain.sh +9636 -0
- data/ext/libeio/missing +376 -0
- data/ext/libeio/xthread.h +166 -0
- data/ext/libev/Changes +125 -7
- data/ext/libev/Makefile.am +5 -3
- data/ext/libev/Makefile.in +209 -120
- data/ext/libev/aclocal.m4 +6027 -4619
- data/ext/libev/autogen.sh +1 -4
- data/ext/libev/config.h.in +11 -7
- data/ext/libev/configure +7312 -14993
- data/ext/libev/configure.ac +12 -5
- data/ext/libev/depcomp +630 -0
- data/ext/libev/ev++.h +48 -32
- data/ext/libev/ev.c +1173 -391
- data/ext/libev/ev.h +315 -181
- data/ext/libev/ev_epoll.c +66 -15
- data/ext/libev/ev_kqueue.c +20 -18
- data/ext/libev/ev_poll.c +27 -23
- data/ext/libev/ev_port.c +39 -19
- data/ext/libev/ev_select.c +23 -17
- data/ext/libev/ev_vars.h +25 -8
- data/ext/libev/ev_win32.c +6 -6
- data/ext/libev/ev_wrap.h +22 -2
- data/ext/libev/event.c +18 -17
- data/ext/libev/event.h +16 -4
- data/ext/libev/libev.m4 +10 -6
- data/ext/libev/ltmain.sh +7353 -5811
- data/ext/nginx/Configuration.c +74 -42
- data/ext/nginx/Configuration.h +3 -5
- data/ext/nginx/ContentHandler.c +26 -83
- data/ext/nginx/ContentHandler.h +1 -1
- data/ext/nginx/config +13 -9
- data/ext/nginx/ngx_http_passenger_module.c +3 -7
- data/ext/oxt/detail/backtrace_enabled.hpp +5 -102
- data/ext/oxt/detail/context.hpp +90 -0
- data/ext/oxt/detail/spin_lock_darwin.hpp +4 -0
- data/ext/oxt/detail/spin_lock_gcc_x86.hpp +4 -0
- data/ext/oxt/detail/spin_lock_pthreads.hpp +14 -0
- data/ext/oxt/detail/tracable_exception_enabled.hpp +2 -2
- data/ext/oxt/dynamic_thread_group.hpp +27 -1
- data/ext/oxt/implementation.cpp +415 -0
- data/ext/oxt/{thread.cpp → initialize.hpp} +13 -6
- data/ext/oxt/macros.hpp +32 -1
- data/ext/oxt/spin_lock.hpp +6 -11
- data/ext/oxt/system_calls.cpp +204 -16
- data/ext/oxt/system_calls.hpp +85 -45
- data/ext/oxt/thread.hpp +13 -117
- data/ext/ruby/passenger_native_support.c +82 -237
- data/helper-scripts/backtrace-sanitizer.rb +114 -0
- data/helper-scripts/classic-rails-loader.rb +135 -0
- data/helper-scripts/classic-rails-preloader.rb +161 -0
- data/helper-scripts/node-loader.js +314 -0
- data/helper-scripts/rack-loader.rb +104 -0
- data/helper-scripts/rack-preloader.rb +132 -0
- data/helper-scripts/wsgi-loader.py +231 -0
- data/helper-scripts/wsgi-preloader.py +1 -0
- data/lib/phusion_passenger.rb +159 -61
- data/lib/phusion_passenger/abstract_installer.rb +182 -87
- data/lib/phusion_passenger/admin_tools/server_instance.rb +25 -19
- data/lib/phusion_passenger/analytics_logger.rb +5 -4
- data/lib/phusion_passenger/classic_rails/{request_handler.rb → thread_handler_extension.rb} +4 -40
- data/lib/phusion_passenger/classic_rails_extensions/init.rb +5 -3
- data/lib/phusion_passenger/common_library.rb +441 -0
- data/lib/phusion_passenger/console_text_template.rb +4 -16
- data/lib/phusion_passenger/constants.rb +1 -8
- data/lib/phusion_passenger/debug_logging.rb +5 -2
- data/lib/phusion_passenger/dependencies.rb +51 -13
- data/lib/phusion_passenger/loader_shared_helpers.rb +318 -0
- data/lib/phusion_passenger/message_channel.rb +3 -47
- data/lib/phusion_passenger/message_client.rb +2 -2
- data/lib/phusion_passenger/native_support.rb +36 -15
- data/lib/phusion_passenger/packaging.rb +8 -11
- data/lib/phusion_passenger/platform_info.rb +25 -17
- data/lib/phusion_passenger/platform_info/apache.rb +10 -7
- data/lib/phusion_passenger/platform_info/binary_compatibility.rb +10 -30
- data/lib/phusion_passenger/platform_info/compiler.rb +93 -34
- data/lib/phusion_passenger/platform_info/ruby.rb +37 -97
- data/lib/phusion_passenger/preloader_shared_helpers.rb +121 -0
- data/lib/phusion_passenger/public_api.rb +1 -4
- data/lib/phusion_passenger/rack/{request_handler.rb → thread_handler_extension.rb} +14 -63
- data/lib/phusion_passenger/rails3_extensions/init.rb +9 -8
- data/lib/phusion_passenger/request_handler.rb +500 -0
- data/lib/phusion_passenger/request_handler/thread_handler.rb +360 -0
- data/lib/phusion_passenger/ruby_core_enhancements.rb +142 -0
- data/lib/phusion_passenger/standalone/command.rb +36 -15
- data/lib/phusion_passenger/standalone/package_runtime_command.rb +16 -8
- data/lib/phusion_passenger/standalone/runtime_installer.rb +169 -72
- data/lib/phusion_passenger/standalone/start_command.rb +44 -39
- data/lib/phusion_passenger/standalone/utils.rb +5 -5
- data/lib/phusion_passenger/utils.rb +35 -914
- data/lib/phusion_passenger/utils/ansi_colors.rb +59 -0
- data/lib/phusion_passenger/utils/file_system_watcher.rb +1 -1
- data/lib/phusion_passenger/utils/robust_interruption.rb +134 -0
- data/lib/phusion_passenger/utils/tee_input.rb +174 -0
- data/lib/phusion_passenger/utils/tmpio.rb +33 -0
- data/lib/phusion_passenger/utils/unseekable_socket.rb +6 -0
- data/resources/mime.types +5 -1
- data/{lib/phusion_passenger/templates → resources}/standalone_default_root/index.html +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/config_snippets.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/deployment_example.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/no_write_permission_to_passenger_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/welcome.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/error_layout.css +6 -0
- data/resources/templates/error_layout.html.template +89 -0
- data/resources/templates/general_error.html.template +1 -0
- data/resources/templates/general_error_with_html.html.template +1 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/ask_for_extra_configure_flags.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/cannot_write_to_dir.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets_inserted.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/confirm_extra_configure_flags.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/deployment_example.txt.erb +0 -0
- data/resources/templates/nginx/not_available_when_natively_packaged.txt.erb +8 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_downloaded.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_extracted.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/query_download_and_install.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/welcome.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/cannot_write_to_dir.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/config.erb +26 -5
- data/{lib/phusion_passenger → resources}/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/welcome.txt.erb +0 -0
- data/resources/templates/undisclosed_error.html.template +25 -0
- data/test/config.json.example +42 -0
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +86 -0
- data/test/cxx/ApplicationPool2/OptionsTest.cpp +44 -0
- data/test/cxx/ApplicationPool2/PoolTest.cpp +1234 -0
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +131 -0
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +229 -0
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +744 -0
- data/test/cxx/BufferedIOTest.cpp +7 -7
- data/test/cxx/CxxTestMain.cpp +65 -2
- data/test/cxx/FileBackedPipeTest.cpp +626 -0
- data/test/cxx/FileChangeCheckerTest.cpp +20 -18
- data/test/cxx/FilterSupportTest.cpp +5 -5
- data/test/cxx/IOUtilsTest.cpp +11 -4
- data/test/cxx/MessageReadersWritersTest.cpp +1 -1
- data/test/cxx/MessageServerTest.cpp +31 -30
- data/test/cxx/RequestHandlerTest.cpp +777 -0
- data/test/cxx/ScgiRequestParserTest.cpp +36 -16
- data/test/cxx/ServerInstanceDirTest.cpp +1 -1
- data/test/cxx/StringMapTest.cpp +61 -0
- data/test/cxx/TemplateTest.cpp +118 -0
- data/test/cxx/TestSupport.cpp +25 -68
- data/test/cxx/TestSupport.h +81 -41
- data/test/cxx/{LoggingTest.cpp → UnionStationTest.cpp} +79 -74
- data/test/cxx/UtilsTest.cpp +59 -5
- data/test/integration_tests/apache2_tests.rb +2 -2
- data/test/integration_tests/nginx_tests.rb +1 -1
- data/test/integration_tests/spec_helper.rb +7 -5
- data/test/oxt/oxt_test_main.cpp +2 -0
- data/test/oxt/syscall_interruption_test.cpp +1 -0
- data/test/ruby/classic_rails/loader_spec.rb +48 -0
- data/test/ruby/classic_rails/preloader_spec.rb +54 -0
- data/test/ruby/rack/loader_spec.rb +62 -0
- data/test/ruby/rack/preloader_spec.rb +74 -0
- data/test/ruby/{abstract_request_handler_spec.rb → request_handler_spec.rb} +31 -68
- data/test/ruby/shared/loader_spec.rb +241 -0
- data/test/ruby/shared/rails/analytics_logging_extensions_spec.rb +141 -182
- data/test/ruby/shared/ruby_loader_spec.rb +55 -0
- data/test/ruby/spec_helper.rb +8 -53
- data/test/ruby/utils/file_system_watcher_spec.rb +9 -1
- data/test/ruby/utils_spec.rb +10 -683
- data/test/stub/rack/config.ru +28 -3
- data/test/stub/rack/start.rb +47 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/Rakefile +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/application_controller.rb +0 -2
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_1.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_2.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/foo_controller.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/helpers/application_helper.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/boot.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/database.yml +3 -3
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environment.rb +5 -2
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/development.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/production.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/staging.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/inflections.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/mime_types.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/routes.rb +1 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/about +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/console +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/dbconsole +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/destroy +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/generate +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/benchmarker +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/profiler +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/request +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/plugin +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/inspector +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/reaper +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/spawner +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/runner +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/server +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/Gemfile +0 -0
- data/test/stub/rails3.0/Gemfile.lock +80 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/Rakefile +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/controllers/application_controller.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/helpers/application_helper.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/views/layouts/application.html.erb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config.ru +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/application.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/boot.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/database.yml +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environment.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/development.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/production.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/test.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/backtrace_silencers.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/inflections.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/mime_types.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/passenger.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/secret_token.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/session_store.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/locales/en.yml +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/routes.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/db/seeds.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/doc/README_FOR_APP +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/404.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/422.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/500.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/favicon.ico +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/index.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/robots.txt +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/script/rails +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/performance/browsing_test.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/test_helper.rb +0 -0
- data/test/stub/start_error.pl +24 -0
- data/test/stub/wsgi/passenger_wsgi.py +71 -3
- data/test/support/apache2_controller.rb +2 -2
- data/test/support/placebo-preloader.rb +88 -0
- data/test/support/test_helper.rb +1 -14
- data/test/tut/tut.h +11 -4
- metadata +590 -326
- data.tar.gz.asc +0 -12
- data/PACKAGING.TXT +0 -25
- data/build/config.rb +0 -46
- data/ext/apache2/HelperAgent.cpp +0 -364
- data/ext/boost/call_traits.hpp +0 -24
- data/ext/boost/detail/call_traits.hpp +0 -164
- data/ext/common/AbstractSpawnManager.h +0 -110
- data/ext/common/AgentBase.cpp +0 -432
- data/ext/common/ApplicationPool/Client.h +0 -788
- data/ext/common/ApplicationPool/Interface.h +0 -295
- data/ext/common/ApplicationPool/Pool.h +0 -1327
- data/ext/common/ApplicationPool/Server.h +0 -479
- data/ext/common/MessageChannel.h +0 -494
- data/ext/common/PoolOptions.h +0 -518
- data/ext/common/Process.h +0 -253
- data/ext/common/Session.h +0 -436
- data/ext/common/SpawnManager.h +0 -611
- data/ext/google/ChangeLog +0 -167
- data/ext/google/dense_hash_map +0 -310
- data/ext/google/dense_hash_set +0 -287
- data/ext/google/sparse_hash_map +0 -294
- data/ext/google/sparse_hash_set +0 -275
- data/ext/google/sparsehash/densehashtable.h +0 -1062
- data/ext/google/sparsehash/sparseconfig.h +0 -55
- data/ext/google/sparsehash/sparsehashtable.h +0 -1015
- data/ext/google/sparsetable +0 -1468
- data/ext/google/type_traits.h +0 -250
- data/ext/nginx/HelperAgent.cpp +0 -1355
- data/ext/nginx/ScgiRequestParser.h +0 -375
- data/ext/oxt/backtrace.cpp +0 -185
- data/ext/oxt/tracable_exception.cpp +0 -89
- data/helper-scripts/passenger-spawn-server +0 -106
- data/lib/phusion_passenger/abstract_request_handler.rb +0 -766
- data/lib/phusion_passenger/abstract_server.rb +0 -372
- data/lib/phusion_passenger/abstract_server_collection.rb +0 -335
- data/lib/phusion_passenger/app_process.rb +0 -174
- data/lib/phusion_passenger/classic_rails/application_spawner.rb +0 -344
- data/lib/phusion_passenger/classic_rails/framework_spawner.rb +0 -311
- data/lib/phusion_passenger/exceptions.rb +0 -103
- data/lib/phusion_passenger/html_template.rb +0 -107
- data/lib/phusion_passenger/rack/application_spawner.rb +0 -231
- data/lib/phusion_passenger/spawn_manager.rb +0 -359
- data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +0 -38
- data/lib/phusion_passenger/templates/app_init_error.html.erb +0 -64
- data/lib/phusion_passenger/templates/database_error.html.erb +0 -66
- data/lib/phusion_passenger/templates/error_layout.html.erb +0 -39
- data/lib/phusion_passenger/templates/framework_init_error.html.erb +0 -39
- data/lib/phusion_passenger/templates/general_error.html.erb +0 -22
- data/lib/phusion_passenger/templates/load_error.html.erb +0 -46
- data/lib/phusion_passenger/templates/version_not_found.html.erb +0 -34
- data/lib/phusion_passenger/utils/rewindable_input.rb +0 -125
- data/lib/phusion_passenger/wsgi/application_spawner.rb +0 -108
- data/test/config.yml.example +0 -41
- data/test/cxx/ApplicationPool_PoolTest.cpp +0 -33
- data/test/cxx/ApplicationPool_PoolTestCases.cpp +0 -1029
- data/test/cxx/ApplicationPool_ServerTest.cpp +0 -308
- data/test/cxx/ApplicationPool_Server_PoolTest.cpp +0 -80
- data/test/cxx/MessageChannelTest.cpp +0 -557
- data/test/cxx/PoolOptionsTest.cpp +0 -116
- data/test/cxx/SpawnManagerTest.cpp +0 -161
- data/test/ruby/abstract_server_collection_spec.rb +0 -247
- data/test/ruby/abstract_server_spec.rb +0 -61
- data/test/ruby/app_process_spec.rb +0 -43
- data/test/ruby/classic_rails/application_spawner_spec.rb +0 -89
- data/test/ruby/classic_rails/framework_spawner_spec.rb +0 -92
- data/test/ruby/rack/application_spawner_spec.rb +0 -116
- data/test/ruby/shared/abstract_server_spec.rb +0 -23
- data/test/ruby/shared/spawners/classic_rails/framework_spawner_spec.rb +0 -38
- data/test/ruby/shared/spawners/classic_rails/lack_of_rails_gem_version_spec.rb +0 -19
- data/test/ruby/shared/spawners/classic_rails/spawner_spec.rb +0 -15
- data/test/ruby/shared/spawners/non_preloading_spawner_spec.rb +0 -27
- data/test/ruby/shared/spawners/preloading_spawner_spec.rb +0 -29
- data/test/ruby/shared/spawners/reload_all_spec.rb +0 -36
- data/test/ruby/shared/spawners/reload_single_spec.rb +0 -52
- data/test/ruby/shared/spawners/spawn_server_spec.rb +0 -28
- data/test/ruby/shared/spawners/spawner_spec.rb +0 -273
- data/test/ruby/shared/utils/pseudo_io_spec.rb +0 -60
- data/test/ruby/spawn_manager_spec.rb +0 -134
- data/test/ruby/wsgi/application_spawner_spec.rb +0 -50
- data/test/stub/message_channel.rb +0 -11
- data/test/stub/message_channel_2.rb +0 -12
- data/test/stub/message_channel_3.rb +0 -19
- data/test/stub/rails_apps/3.0/empty/Gemfile.lock +0 -73
- data/test/stub/spawn_server.rb +0 -22
- metadata.gz.asc +0 -12
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,89 @@
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
5
|
+
<meta name="generator" content="Phusion Passenger">
|
6
|
+
<title>{{TITLE}}</title>
|
7
|
+
<style type="text/css">
|
8
|
+
{{CSS|raw}}
|
9
|
+
</style>
|
10
|
+
<link rel="stylesheet" type="text/css" href="http://www.modrails.com/error_pages/1.0/error_page.css">
|
11
|
+
<style type="text/css">
|
12
|
+
dd {
|
13
|
+
text-align: left;
|
14
|
+
}
|
15
|
+
|
16
|
+
dd pre {
|
17
|
+
margin-top: 0;
|
18
|
+
margin-bottom: 0;
|
19
|
+
}
|
20
|
+
</style>
|
21
|
+
</head>
|
22
|
+
|
23
|
+
<body>
|
24
|
+
|
25
|
+
<div id="site_container">
|
26
|
+
<div id="site_header">
|
27
|
+
<ul class="corporate_identity">
|
28
|
+
<li class="logo"><a href="https://www.phusionpassenger.com"><span>Phusion Passenger</span></a></li>
|
29
|
+
</ul>
|
30
|
+
</div>
|
31
|
+
<div id="site_body">
|
32
|
+
<h1 class="error_title">{{TITLE}}</h1>
|
33
|
+
<div id="content">
|
34
|
+
{{CONTENT|raw}}
|
35
|
+
|
36
|
+
<dl>
|
37
|
+
<dt>Application root</dt>
|
38
|
+
<dd>{{APP_ROOT}}</dd>
|
39
|
+
<dt>Environment (value of RAILS_ENV, RACK_ENV, WSGI_ENV and PASSENGER_ENV)</dt>
|
40
|
+
<dd>{{ENVIRONMENT}}</dd>
|
41
|
+
{{if IS_RUBY_APP}}
|
42
|
+
<dt>Ruby interpreter command</dt>
|
43
|
+
<dd><pre>{{RUBY}}</pre></dd>
|
44
|
+
{{/if}}
|
45
|
+
<dt>User and groups</dt>
|
46
|
+
<dd><pre>{{USER_INFO|default=Unknown}}</pre></dd>
|
47
|
+
<dt>Environment variables</dt>
|
48
|
+
<dd><pre>{{ENVVARS|default=Unknown}}</pre></dd>
|
49
|
+
<dt>Ulimits</dt>
|
50
|
+
<dd><pre>{{ULIMIT|default=Unknown}}</pre></dd>
|
51
|
+
{{if RUBY_INFO}}
|
52
|
+
<dt>General Ruby interpreter information</dt>
|
53
|
+
<dd><pre>{{RUBY_INFO}}</pre></dd>
|
54
|
+
{{/if}}
|
55
|
+
{{if RBCONFIG}}
|
56
|
+
<dt>Ruby configuration (RbConfig::CONFIG)</dt>
|
57
|
+
<dd><pre>{{RBCONFIG}}</pre></dd>
|
58
|
+
{{/if}}
|
59
|
+
{{if ACTIVATED_GEMS}}
|
60
|
+
<dt>Activated Ruby gems</dt>
|
61
|
+
<dd><pre>{{ACTIVATED_GEMS}}</pre></dd>
|
62
|
+
{{/if}}
|
63
|
+
{{if LOAD_PATH}}
|
64
|
+
<dt>Ruby load path ($LOAD_PATH)</dt>
|
65
|
+
<dd><pre>{{LOAD_PATH}}</pre></dd>
|
66
|
+
{{/if}}
|
67
|
+
{{if LOADED_LIBS}}
|
68
|
+
<dt>Ruby loaded libraries ($LOADED_FEATURES)</dt>
|
69
|
+
<dd><pre>{{LOADED_LIBS}}</pre></dd>
|
70
|
+
{{/if}}
|
71
|
+
</dl>
|
72
|
+
</div>
|
73
|
+
</div>
|
74
|
+
<div id="site_footer">
|
75
|
+
<!--
|
76
|
+
You are free to modify the footer as you see fit,
|
77
|
+
but we kindly ask of you to preserve to following
|
78
|
+
text. Thank you.
|
79
|
+
-->
|
80
|
+
<div class="container">
|
81
|
+
Powered by <a href="https://www.phusionpassenger.com/">Phusion Passenger</a>,
|
82
|
+
<tt>mod_rails</tt> / <tt>mod_rack</tt> for Apache and Nginx.
|
83
|
+
</div>
|
84
|
+
</div>
|
85
|
+
</div>
|
86
|
+
|
87
|
+
</body>
|
88
|
+
</html>
|
89
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
<pre>{{MESSAGE}}</pre>
|
@@ -0,0 +1 @@
|
|
1
|
+
{{MESSAGE}}
|
data/{lib/phusion_passenger → resources}/templates/nginx/ask_for_extra_configure_flags.txt.erb
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/{lib/phusion_passenger → resources}/templates/nginx/confirm_extra_configure_flags.txt.erb
RENAMED
File without changes
|
File without changes
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<red>passenger-install-nginx-module is not available when packaged</red>
|
2
|
+
|
3
|
+
This Phusion Passenger installation is provided by your packager (as opposed to being installed from source). As such, you cannot use passenger-install-nginx-module. If you want to use passenger-install-nginx-module, please install Phusion Passenger from source by downloading it from <b>www.modrails.com</b>.
|
4
|
+
|
5
|
+
For more information about using Phusion Passenger for Nginx, please consult the documentation at one of the following places:
|
6
|
+
|
7
|
+
* <b><%= PhusionPassenger.doc_dir %>/Users Guide Nginx.html</b>
|
8
|
+
* <b>http://www.modrails.com/documentation.html</b>
|
data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_downloaded.txt.erb
RENAMED
File without changes
|
data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_extracted.txt.erb
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -37,9 +37,9 @@ events {
|
|
37
37
|
|
38
38
|
http {
|
39
39
|
log_format debug '[$time_local] $msec "$request" $status conn=$connection sent=$bytes_sent body_sent=$body_bytes_sent';
|
40
|
-
include '<%= PhusionPassenger
|
40
|
+
include '<%= PhusionPassenger.resources_dir %>/mime.types';
|
41
41
|
passenger_ruby <%= PlatformInfo.ruby_command %>;
|
42
|
-
passenger_root '<%=
|
42
|
+
passenger_root '<%= @location_config_filename %>';
|
43
43
|
passenger_abort_on_startup_error on;
|
44
44
|
passenger_user_switching off;
|
45
45
|
passenger_max_pool_size <%= @options[:max_pool_size] %>;
|
@@ -47,7 +47,6 @@ http {
|
|
47
47
|
<% if @options[:user] %>passenger_default_user <%= @options[:user] %>;<% end %>
|
48
48
|
<% if debugging? %>passenger_log_level 2;<% end %>
|
49
49
|
<% if @options[:rolling_restarts] %>passenger_rolling_restarts on;<% end %>
|
50
|
-
<% if @options[:resist_deployment_errors] %>passenger_resist_deployment_errors on;<% end %>
|
51
50
|
|
52
51
|
<% if @options[:union_station_gateway_address] %>
|
53
52
|
union_station_gateway_address <%= @options[:union_station_gateway_address] %>;
|
@@ -69,14 +68,14 @@ http {
|
|
69
68
|
# Default server entry.
|
70
69
|
server {
|
71
70
|
listen <%= nginx_listen_address %>;
|
72
|
-
root '<%=
|
71
|
+
root '<%= PhusionPassenger.resources_dir %>/standalone_default_root';
|
73
72
|
}
|
74
73
|
<% end %>
|
75
74
|
|
76
75
|
<% if @options[:ping_port] %>
|
77
76
|
server {
|
78
77
|
listen <%= nginx_listen_address(@options, true) %>;
|
79
|
-
root '<%=
|
78
|
+
root '<%= PhusionPassenger.resources_dir %>/standalone_default_root';
|
80
79
|
}
|
81
80
|
<% end %>
|
82
81
|
|
@@ -93,6 +92,28 @@ http {
|
|
93
92
|
union_station_support on;
|
94
93
|
union_station_key <%= app[:union_station_key] %>;
|
95
94
|
<% end %>
|
95
|
+
|
96
|
+
location ~ ^/assets/ {
|
97
|
+
error_page 490 = @static_asset;
|
98
|
+
error_page 491 = @dynamic_request;
|
99
|
+
recursive_error_pages on;
|
100
|
+
|
101
|
+
if (-f $request_filename) {
|
102
|
+
return 490;
|
103
|
+
}
|
104
|
+
if (!-f $request_filename) {
|
105
|
+
return 491;
|
106
|
+
}
|
107
|
+
}
|
108
|
+
location @static_asset {
|
109
|
+
gzip_static on;
|
110
|
+
expires max;
|
111
|
+
add_header Cache-Control public;
|
112
|
+
add_header ETag "";
|
113
|
+
}
|
114
|
+
location @dynamic_request {
|
115
|
+
passenger_enabled on;
|
116
|
+
}
|
96
117
|
}
|
97
118
|
passenger_pre_start http://<%= nginx_listen_address(app) %>;
|
98
119
|
<% end %>
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
5
|
+
<style type="text/css">
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
7
|
+
div.dialog {
|
8
|
+
width: 25em;
|
9
|
+
padding: 0 4em;
|
10
|
+
margin: 4em auto 0 auto;
|
11
|
+
border: 1px solid #ccc;
|
12
|
+
border-right-color: #999;
|
13
|
+
border-bottom-color: #999;
|
14
|
+
}
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body>
|
20
|
+
<div class="dialog">
|
21
|
+
<h1>We're sorry, but something went wrong.</h1>
|
22
|
+
<p>We've been notified about this issue and we'll take a look at it shortly.</p>
|
23
|
+
</div>
|
24
|
+
</body>
|
25
|
+
</html>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
{
|
2
|
+
//// This file contains system-specific configuration options that the test suite needs.
|
3
|
+
//// Please customize it for your system.
|
4
|
+
|
5
|
+
// These are the usernames and group names of normal, non-administrator
|
6
|
+
// users and groups. Preferably, these are user and group accounts that
|
7
|
+
// are normally not used.
|
8
|
+
//
|
9
|
+
// These users and groups MUST be able to access this 'test' directory,
|
10
|
+
// otherwise the tests will fail.
|
11
|
+
|
12
|
+
//// Good values for OS X:
|
13
|
+
"normal_user_1": "_www",
|
14
|
+
"normal_user_2": "daemon",
|
15
|
+
// Must not be "nobody".
|
16
|
+
"default_user": "_sandbox",
|
17
|
+
// Must not be normal_user_1's primary group.
|
18
|
+
"normal_group_1": "daemon",
|
19
|
+
// Must not be normal_user_2's primary group.
|
20
|
+
"normal_group_2": "_sandbox",
|
21
|
+
// Must not be default_user's primary group. Must not be "nobody".
|
22
|
+
"default_group": "_www",
|
23
|
+
|
24
|
+
///// Good values for Linux and FreeBSD. Same restrictions apply.
|
25
|
+
//"normal_user_1": "games",
|
26
|
+
//"normal_user_2": "daemon",
|
27
|
+
//"default_user": "man",
|
28
|
+
//"normal_group_1": "daemon",
|
29
|
+
//"normal_group_2": "man",
|
30
|
+
//"default_group": "games",
|
31
|
+
|
32
|
+
// A nonexistant username, group name, user ID and group ID.
|
33
|
+
"nonexistant_user": "xxxxxxxxxxxxxxxxxxx",
|
34
|
+
"nonexistant_group": "xxxxxxxxxxxxxxxxxxx",
|
35
|
+
"nonexistant_uid": 9999,
|
36
|
+
"nonexistant_gid": 9999,
|
37
|
+
|
38
|
+
// If you want to run the Nginx integration tests, then set the following
|
39
|
+
// config option to the full path of the Nginx binary. This Nginx binary *must*
|
40
|
+
// be compiled with Phusion Passenger support!
|
41
|
+
// nginx: /usr/local/sbin/nginx
|
42
|
+
}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#include <TestSupport.h>
|
2
|
+
#include <ApplicationPool2/Spawner.h>
|
3
|
+
#include <Utils/json.h>
|
4
|
+
|
5
|
+
using namespace Passenger;
|
6
|
+
using namespace Passenger::ApplicationPool2;
|
7
|
+
|
8
|
+
namespace tut {
|
9
|
+
struct ApplicationPool2_DirectSpawnerTest {
|
10
|
+
ServerInstanceDirPtr serverInstanceDir;
|
11
|
+
ServerInstanceDir::GenerationPtr generation;
|
12
|
+
BackgroundEventLoop bg;
|
13
|
+
|
14
|
+
ApplicationPool2_DirectSpawnerTest() {
|
15
|
+
createServerInstanceDirAndGeneration(serverInstanceDir, generation);
|
16
|
+
bg.start();
|
17
|
+
}
|
18
|
+
|
19
|
+
~ApplicationPool2_DirectSpawnerTest() {
|
20
|
+
unlink("stub/wsgi/passenger_wsgi.pyc");
|
21
|
+
}
|
22
|
+
|
23
|
+
shared_ptr<DirectSpawner> createSpawner(const Options &options) {
|
24
|
+
return make_shared<DirectSpawner>(bg.safe,
|
25
|
+
*resourceLocator, generation);
|
26
|
+
}
|
27
|
+
|
28
|
+
Options createOptions() {
|
29
|
+
Options options;
|
30
|
+
options.spawnMethod = "direct";
|
31
|
+
options.loadShellEnvvars = false;
|
32
|
+
return options;
|
33
|
+
}
|
34
|
+
};
|
35
|
+
|
36
|
+
DEFINE_TEST_GROUP_WITH_LIMIT(ApplicationPool2_DirectSpawnerTest, 90);
|
37
|
+
|
38
|
+
#include "SpawnerTestCases.cpp"
|
39
|
+
|
40
|
+
TEST_METHOD(80) {
|
41
|
+
// If the application didn't start within the timeout
|
42
|
+
// then whatever was written to stderr is used as the
|
43
|
+
// SpawnException error page.
|
44
|
+
Options options = createOptions();
|
45
|
+
options.appRoot = "stub";
|
46
|
+
options.startCommand = "perl\1" "-e\1" "print STDERR \"hello world\\n\"; sleep(60)";
|
47
|
+
options.startupFile = ".";
|
48
|
+
options.startTimeout = 300;
|
49
|
+
|
50
|
+
DirectSpawner spawner(bg.safe, *resourceLocator, generation);
|
51
|
+
spawner.forwardStderr = false;
|
52
|
+
|
53
|
+
try {
|
54
|
+
spawner.spawn(options);
|
55
|
+
fail("Timeout expected");
|
56
|
+
} catch (const SpawnException &e) {
|
57
|
+
ensure_equals(e.getErrorKind(),
|
58
|
+
SpawnException::APP_STARTUP_TIMEOUT);
|
59
|
+
ensure_equals(e.getErrorPage(),
|
60
|
+
"hello world\n");
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
TEST_METHOD(81) {
|
65
|
+
// If the application crashed during startup without returning
|
66
|
+
// a proper error response, then its stderr output is used
|
67
|
+
// as error response instead.
|
68
|
+
Options options = createOptions();
|
69
|
+
options.appRoot = "stub";
|
70
|
+
options.startCommand = "perl\1" "-e\1" "print STDERR \"hello world\\n\"";
|
71
|
+
options.startupFile = ".";
|
72
|
+
|
73
|
+
DirectSpawner spawner(bg.safe, *resourceLocator, generation);
|
74
|
+
spawner.forwardStderr = false;
|
75
|
+
|
76
|
+
try {
|
77
|
+
spawner.spawn(options);
|
78
|
+
fail("SpawnException expected");
|
79
|
+
} catch (const SpawnException &e) {
|
80
|
+
ensure_equals(e.getErrorKind(),
|
81
|
+
SpawnException::APP_STARTUP_PROTOCOL_ERROR);
|
82
|
+
ensure_equals(e.getErrorPage(),
|
83
|
+
"hello world\n");
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#include <TestSupport.h>
|
2
|
+
#include <ApplicationPool2/Process.h>
|
3
|
+
|
4
|
+
using namespace Passenger;
|
5
|
+
using namespace Passenger::ApplicationPool2;
|
6
|
+
using namespace std;
|
7
|
+
|
8
|
+
namespace tut {
|
9
|
+
struct ApplicationPool2_OptionsTest {
|
10
|
+
ApplicationPool2_OptionsTest() {
|
11
|
+
}
|
12
|
+
};
|
13
|
+
|
14
|
+
DEFINE_TEST_GROUP(ApplicationPool2_OptionsTest);
|
15
|
+
|
16
|
+
TEST_METHOD(1) {
|
17
|
+
// Test persist().
|
18
|
+
char appRoot[] = "appRoot";
|
19
|
+
char processTitle[] = "processTitle";
|
20
|
+
char fooKey[] = "PASSENGER_FOO";
|
21
|
+
char fooValue[] = "foo";
|
22
|
+
char barKey[] = "PASSENGER_BAR";
|
23
|
+
char barValue[] = "bar";
|
24
|
+
|
25
|
+
Options options;
|
26
|
+
options.appRoot = appRoot;
|
27
|
+
options.processTitle = processTitle;
|
28
|
+
options.environmentVariables.push_back(make_pair(fooKey, fooValue));
|
29
|
+
options.environmentVariables.push_back(make_pair(barKey, barValue));
|
30
|
+
|
31
|
+
Options options2 = options.copyAndPersist();
|
32
|
+
appRoot[0] = processTitle[0] = 'x';
|
33
|
+
fooKey[0] = fooValue[0] = 'x';
|
34
|
+
barKey[0] = barValue[0] = 'x';
|
35
|
+
|
36
|
+
ensure_equals(options2.appRoot, "appRoot");
|
37
|
+
ensure_equals(options2.processTitle, "processTitle");
|
38
|
+
ensure_equals(options2.environmentVariables.size(), 2u);
|
39
|
+
ensure_equals(options2.environmentVariables[0].first, "PASSENGER_FOO");
|
40
|
+
ensure_equals(options2.environmentVariables[0].second, "foo");
|
41
|
+
ensure_equals(options2.environmentVariables[1].first, "PASSENGER_BAR");
|
42
|
+
ensure_equals(options2.environmentVariables[1].second, "bar");
|
43
|
+
}
|
44
|
+
}
|
@@ -0,0 +1,1234 @@
|
|
1
|
+
#include <TestSupport.h>
|
2
|
+
#include <ApplicationPool2/Pool.h>
|
3
|
+
#include <Utils/IOUtils.h>
|
4
|
+
#include <Utils/StrIntUtils.h>
|
5
|
+
#include <Utils/json.h>
|
6
|
+
#include <MessageReadersWriters.h>
|
7
|
+
#include <map>
|
8
|
+
#include <vector>
|
9
|
+
#include <cerrno>
|
10
|
+
#include <signal.h>
|
11
|
+
|
12
|
+
using namespace std;
|
13
|
+
using namespace Passenger;
|
14
|
+
using namespace Passenger::ApplicationPool2;
|
15
|
+
|
16
|
+
namespace tut {
|
17
|
+
struct ApplicationPool2_PoolTest {
|
18
|
+
ServerInstanceDirPtr serverInstanceDir;
|
19
|
+
ServerInstanceDir::GenerationPtr generation;
|
20
|
+
BackgroundEventLoop bg;
|
21
|
+
SpawnerFactoryPtr spawnerFactory;
|
22
|
+
PoolPtr pool;
|
23
|
+
GetCallback callback;
|
24
|
+
SessionPtr currentSession;
|
25
|
+
ExceptionPtr currentException;
|
26
|
+
AtomicInt number;
|
27
|
+
boost::mutex syncher;
|
28
|
+
list<SessionPtr> sessions;
|
29
|
+
bool retainSessions;
|
30
|
+
|
31
|
+
ApplicationPool2_PoolTest() {
|
32
|
+
createServerInstanceDirAndGeneration(serverInstanceDir, generation);
|
33
|
+
retainSessions = false;
|
34
|
+
spawnerFactory = make_shared<SpawnerFactory>(bg.safe, *resourceLocator, generation);
|
35
|
+
pool = make_shared<Pool>(bg.safe.get(), spawnerFactory);
|
36
|
+
bg.start();
|
37
|
+
callback = boost::bind(&ApplicationPool2_PoolTest::_callback, this, _1, _2);
|
38
|
+
}
|
39
|
+
|
40
|
+
~ApplicationPool2_PoolTest() {
|
41
|
+
// Explicitly destroy these here because they can run
|
42
|
+
// additional code that depend on other fields in this
|
43
|
+
// class.
|
44
|
+
setLogLevel(0);
|
45
|
+
TRACE_POINT();
|
46
|
+
pool->destroy();
|
47
|
+
UPDATE_TRACE_POINT();
|
48
|
+
pool.reset();
|
49
|
+
UPDATE_TRACE_POINT();
|
50
|
+
lock_guard<boost::mutex> l(syncher);
|
51
|
+
currentSession.reset();
|
52
|
+
sessions.clear();
|
53
|
+
}
|
54
|
+
|
55
|
+
Options createOptions() {
|
56
|
+
Options options;
|
57
|
+
options.spawnMethod = "dummy";
|
58
|
+
options.appRoot = "stub/rack";
|
59
|
+
options.startCommand = "ruby\1" "start.rb";
|
60
|
+
options.startupFile = "start.rb";
|
61
|
+
options.loadShellEnvvars = false;
|
62
|
+
options.user = testConfig["normal_user_1"].asCString();
|
63
|
+
options.defaultUser = testConfig["default_user"].asCString();
|
64
|
+
options.defaultGroup = testConfig["default_group"].asCString();
|
65
|
+
return options;
|
66
|
+
}
|
67
|
+
|
68
|
+
void _callback(const SessionPtr &session, const ExceptionPtr &e) {
|
69
|
+
SessionPtr oldSession;
|
70
|
+
{
|
71
|
+
LockGuard l(syncher);
|
72
|
+
oldSession = currentSession;
|
73
|
+
currentSession = session;
|
74
|
+
currentException = e;
|
75
|
+
number++;
|
76
|
+
if (retainSessions && session != NULL) {
|
77
|
+
sessions.push_back(session);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
// destroy old session object outside the lock.
|
81
|
+
}
|
82
|
+
|
83
|
+
void sendHeaders(int connection, ...) {
|
84
|
+
va_list ap;
|
85
|
+
const char *arg;
|
86
|
+
vector<StaticString> args;
|
87
|
+
|
88
|
+
va_start(ap, connection);
|
89
|
+
while ((arg = va_arg(ap, const char *)) != NULL) {
|
90
|
+
args.push_back(StaticString(arg, strlen(arg) + 1));
|
91
|
+
}
|
92
|
+
va_end(ap);
|
93
|
+
|
94
|
+
shared_array<StaticString> args_array(new StaticString[args.size() + 1]);
|
95
|
+
unsigned int totalSize = 0;
|
96
|
+
for (unsigned int i = 0; i < args.size(); i++) {
|
97
|
+
args_array[i + 1] = args[i];
|
98
|
+
totalSize += args[i].size();
|
99
|
+
}
|
100
|
+
char sizeHeader[sizeof(uint32_t)];
|
101
|
+
Uint32Message::generate(sizeHeader, totalSize);
|
102
|
+
args_array[0] = StaticString(sizeHeader, sizeof(uint32_t));
|
103
|
+
|
104
|
+
gatheredWrite(connection, args_array.get(), args.size() + 1, NULL);
|
105
|
+
}
|
106
|
+
|
107
|
+
string stripHeaders(const string &str) {
|
108
|
+
string::size_type pos = str.find("\r\n\r\n");
|
109
|
+
if (pos == string::npos) {
|
110
|
+
return str;
|
111
|
+
} else {
|
112
|
+
string result = str;
|
113
|
+
result.erase(0, pos + 4);
|
114
|
+
return result;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
string sendRequest(const Options &options, const char *path) {
|
119
|
+
int oldNumber = number;
|
120
|
+
pool->asyncGet(options, callback);
|
121
|
+
EVENTUALLY(5,
|
122
|
+
result = number == oldNumber + 1;
|
123
|
+
);
|
124
|
+
if (currentException != NULL) {
|
125
|
+
P_ERROR("get() exception: " << currentException->what());
|
126
|
+
abort();
|
127
|
+
}
|
128
|
+
currentSession->initiate();
|
129
|
+
sendHeaders(currentSession->fd(),
|
130
|
+
"PATH_INFO", path,
|
131
|
+
"REQUEST_METHOD", "GET",
|
132
|
+
NULL);
|
133
|
+
shutdown(currentSession->fd(), SHUT_WR);
|
134
|
+
string body = stripHeaders(readAll(currentSession->fd()));
|
135
|
+
ProcessPtr process = currentSession->getProcess();
|
136
|
+
currentSession.reset();
|
137
|
+
EVENTUALLY(5,
|
138
|
+
result = process->utilization() == 0;
|
139
|
+
);
|
140
|
+
return body;
|
141
|
+
}
|
142
|
+
};
|
143
|
+
|
144
|
+
DEFINE_TEST_GROUP_WITH_LIMIT(ApplicationPool2_PoolTest, 100);
|
145
|
+
|
146
|
+
TEST_METHOD(1) {
|
147
|
+
// Test initial state.
|
148
|
+
ensure(!pool->atFullCapacity());
|
149
|
+
}
|
150
|
+
|
151
|
+
|
152
|
+
/*********** Test asyncGet() behavior on a single SuperGroup and Group ***********/
|
153
|
+
|
154
|
+
TEST_METHOD(2) {
|
155
|
+
// asyncGet() actions on empty pools cannot be immediately satisfied.
|
156
|
+
// Instead a new process will be spawned. In the mean time get()
|
157
|
+
// actions are put on a wait list which will be processed as soon
|
158
|
+
// as the new process is done spawning.
|
159
|
+
Options options = createOptions();
|
160
|
+
|
161
|
+
ScopedLock l(pool->syncher);
|
162
|
+
pool->asyncGet(options, callback, false);
|
163
|
+
ensure_equals(number, 0);
|
164
|
+
ensure(pool->getWaitlist.empty());
|
165
|
+
ensure(!pool->superGroups.empty());
|
166
|
+
l.unlock();
|
167
|
+
|
168
|
+
EVENTUALLY(5,
|
169
|
+
result = pool->getProcessCount() == 1;
|
170
|
+
);
|
171
|
+
ensure_equals(number, 1);
|
172
|
+
ensure(currentSession != NULL);
|
173
|
+
ensure(currentException == NULL);
|
174
|
+
}
|
175
|
+
|
176
|
+
TEST_METHOD(3) {
|
177
|
+
// If one matching process already exists and it's not at full
|
178
|
+
// capacity then asyncGet() will immediately use it.
|
179
|
+
Options options = createOptions();
|
180
|
+
|
181
|
+
// Spawn a process and opens a session with it.
|
182
|
+
pool->asyncGet(options, callback);
|
183
|
+
EVENTUALLY(5,
|
184
|
+
result = number == 1;
|
185
|
+
);
|
186
|
+
|
187
|
+
// Close the session so that the process is now idle.
|
188
|
+
ProcessPtr process = currentSession->getProcess();
|
189
|
+
currentSession.reset();
|
190
|
+
ensure_equals(process->utilization(), 0);
|
191
|
+
ensure(!process->atFullCapacity());
|
192
|
+
|
193
|
+
// Verify test assertion.
|
194
|
+
ScopedLock l(pool->syncher);
|
195
|
+
pool->asyncGet(options, callback, false);
|
196
|
+
ensure_equals("callback is immediately called", number, 2);
|
197
|
+
}
|
198
|
+
|
199
|
+
TEST_METHOD(4) {
|
200
|
+
// If one matching process already exists but it's at full capacity,
|
201
|
+
// and the limits prevent spawning of a new process,
|
202
|
+
// then asyncGet() will put the get action on the group's wait
|
203
|
+
// queue. When the process is no longer at full capacity it will
|
204
|
+
// process the request.
|
205
|
+
|
206
|
+
// Spawn a process and verify that it's at full capacity.
|
207
|
+
// Keep its session open.
|
208
|
+
Options options = createOptions();
|
209
|
+
options.appGroupName = "test";
|
210
|
+
pool->setMax(1);
|
211
|
+
pool->asyncGet(options, callback);
|
212
|
+
EVENTUALLY(5,
|
213
|
+
result = number == 1;
|
214
|
+
);
|
215
|
+
SessionPtr session1 = currentSession;
|
216
|
+
ProcessPtr process = session1->getProcess();
|
217
|
+
currentSession.reset();
|
218
|
+
ensure_equals(process->sessions, 1);
|
219
|
+
ensure(process->atFullCapacity());
|
220
|
+
|
221
|
+
// Now call asyncGet() again.
|
222
|
+
pool->asyncGet(options, callback);
|
223
|
+
ensure_equals("callback is not yet called", number, 1);
|
224
|
+
ensure_equals("the get action has been put on the wait list",
|
225
|
+
pool->superGroups.get("test")->defaultGroup->getWaitlist.size(), 1u);
|
226
|
+
|
227
|
+
session1.reset();
|
228
|
+
ensure_equals("callback is called after the process becomes idle",
|
229
|
+
number, 2);
|
230
|
+
ensure_equals("the get wait list has been processed",
|
231
|
+
pool->superGroups.get("test")->defaultGroup->getWaitlist.size(), 0u);
|
232
|
+
ensure_equals(process->sessions, 1);
|
233
|
+
}
|
234
|
+
|
235
|
+
TEST_METHOD(5) {
|
236
|
+
// If one matching process already exists but it's at full capacity,
|
237
|
+
// and the limits and pool capacity allow spawning of a new process,
|
238
|
+
// then get() will put the get action on the group's wait
|
239
|
+
// queue while spawning a process in the background.
|
240
|
+
// Either the existing process or the newly spawned process
|
241
|
+
// will process the action, whichever becomes first available.
|
242
|
+
|
243
|
+
// Here we test the case in which the existing process becomes
|
244
|
+
// available first.
|
245
|
+
|
246
|
+
// Spawn a regular process and keep its session open.
|
247
|
+
Options options = createOptions();
|
248
|
+
pool->asyncGet(options, callback);
|
249
|
+
EVENTUALLY(5,
|
250
|
+
result = number == 1;
|
251
|
+
);
|
252
|
+
SessionPtr session1 = currentSession;
|
253
|
+
ProcessPtr process1 = currentSession->getProcess();
|
254
|
+
currentSession.reset();
|
255
|
+
|
256
|
+
// Now spawn a process that never finishes.
|
257
|
+
SpawnerPtr spawner = process1->getGroup()->spawner;
|
258
|
+
dynamic_pointer_cast<DummySpawner>(spawner)->spawnTime = 5000000;
|
259
|
+
pool->asyncGet(options, callback);
|
260
|
+
|
261
|
+
// Release the session on the first process.
|
262
|
+
session1.reset();
|
263
|
+
|
264
|
+
ensure_equals("The callback should have been called twice now", number, 2);
|
265
|
+
ensure_equals("The first process handled the second asyncGet() request",
|
266
|
+
currentSession->getProcess(), process1);
|
267
|
+
}
|
268
|
+
|
269
|
+
TEST_METHOD(6) {
|
270
|
+
// Here we test the case in which the new process becomes
|
271
|
+
// available first.
|
272
|
+
|
273
|
+
// Spawn a regular process.
|
274
|
+
Options options = createOptions();
|
275
|
+
pool->asyncGet(options, callback);
|
276
|
+
EVENTUALLY(5,
|
277
|
+
result = number == 1;
|
278
|
+
);
|
279
|
+
SessionPtr session1 = currentSession;
|
280
|
+
ProcessPtr process1 = currentSession->getProcess();
|
281
|
+
currentSession.reset();
|
282
|
+
|
283
|
+
// As long as we don't release process1 the following get
|
284
|
+
// action will be processed by the newly spawned process.
|
285
|
+
pool->asyncGet(options, callback);
|
286
|
+
EVENTUALLY(5,
|
287
|
+
result = pool->getProcessCount() == 2;
|
288
|
+
);
|
289
|
+
ensure_equals(number, 2);
|
290
|
+
ensure(currentSession->getProcess() != process1);
|
291
|
+
}
|
292
|
+
|
293
|
+
TEST_METHOD(7) {
|
294
|
+
// If multiple matching processes exist, and one of them is idle,
|
295
|
+
// then asyncGet() will use that.
|
296
|
+
|
297
|
+
// Spawn 3 processes and keep a session open with 1 of them.
|
298
|
+
Options options = createOptions();
|
299
|
+
options.minProcesses = 3;
|
300
|
+
pool->asyncGet(options, callback);
|
301
|
+
EVENTUALLY(5,
|
302
|
+
result = number == 1;
|
303
|
+
);
|
304
|
+
EVENTUALLY(5,
|
305
|
+
result = pool->getProcessCount() == 3;
|
306
|
+
);
|
307
|
+
SessionPtr session1 = currentSession;
|
308
|
+
ProcessPtr process1 = currentSession->getProcess();
|
309
|
+
currentSession.reset();
|
310
|
+
|
311
|
+
// Now open another session. It should complete immediately
|
312
|
+
// and should not use the first process.
|
313
|
+
ScopedLock l(pool->syncher);
|
314
|
+
pool->asyncGet(options, callback, false);
|
315
|
+
ensure_equals("asyncGet() completed immediately", number, 2);
|
316
|
+
SessionPtr session2 = currentSession;
|
317
|
+
ProcessPtr process2 = currentSession->getProcess();
|
318
|
+
l.unlock();
|
319
|
+
currentSession.reset();
|
320
|
+
ensure(process2 != process1);
|
321
|
+
|
322
|
+
// Now open yet another session. It should also complete immediately
|
323
|
+
// and should not use the first or the second process.
|
324
|
+
l.lock();
|
325
|
+
pool->asyncGet(options, callback, false);
|
326
|
+
ensure_equals("asyncGet() completed immediately", number, 3);
|
327
|
+
SessionPtr session3 = currentSession;
|
328
|
+
ProcessPtr process3 = currentSession->getProcess();
|
329
|
+
l.unlock();
|
330
|
+
currentSession.reset();
|
331
|
+
ensure(process3 != process1);
|
332
|
+
ensure(process3 != process2);
|
333
|
+
}
|
334
|
+
|
335
|
+
TEST_METHOD(8) {
|
336
|
+
// If multiple matching processes exist, then asyncGet() will use
|
337
|
+
// the one with the smallest utilization number.
|
338
|
+
|
339
|
+
// Spawn 2 processes, each with a concurrency of 2.
|
340
|
+
Options options = createOptions();
|
341
|
+
options.minProcesses = 2;
|
342
|
+
pool->setMax(2);
|
343
|
+
GroupPtr group = pool->findOrCreateGroup(options);
|
344
|
+
dynamic_pointer_cast<DummySpawner>(group->spawner)->concurrency = 2;
|
345
|
+
{
|
346
|
+
LockGuard l(pool->syncher);
|
347
|
+
group->spawn();
|
348
|
+
}
|
349
|
+
EVENTUALLY(5,
|
350
|
+
result = pool->getProcessCount() == 2;
|
351
|
+
);
|
352
|
+
|
353
|
+
// asyncGet() selects some process.
|
354
|
+
pool->asyncGet(options, callback);
|
355
|
+
ensure_equals(number, 1);
|
356
|
+
SessionPtr session1 = currentSession;
|
357
|
+
ProcessPtr process1 = currentSession->getProcess();
|
358
|
+
currentSession.reset();
|
359
|
+
|
360
|
+
// The first process now has 1 session, so next asyncGet() should
|
361
|
+
// select the other process.
|
362
|
+
pool->asyncGet(options, callback);
|
363
|
+
ensure_equals(number, 2);
|
364
|
+
SessionPtr session2 = currentSession;
|
365
|
+
ProcessPtr process2 = currentSession->getProcess();
|
366
|
+
currentSession.reset();
|
367
|
+
ensure("(1)", process1 != process2);
|
368
|
+
|
369
|
+
// Both processes now have an equal number of sessions. Next asyncGet()
|
370
|
+
// can select either.
|
371
|
+
pool->asyncGet(options, callback);
|
372
|
+
ensure_equals(number, 3);
|
373
|
+
SessionPtr session3 = currentSession;
|
374
|
+
ProcessPtr process3 = currentSession->getProcess();
|
375
|
+
currentSession.reset();
|
376
|
+
|
377
|
+
// One process now has the lowest number of sessions. Next
|
378
|
+
// asyncGet() should select that one.
|
379
|
+
pool->asyncGet(options, callback);
|
380
|
+
ensure_equals(number, 4);
|
381
|
+
SessionPtr session4 = currentSession;
|
382
|
+
ProcessPtr process4 = currentSession->getProcess();
|
383
|
+
currentSession.reset();
|
384
|
+
ensure(process3 != process4);
|
385
|
+
}
|
386
|
+
|
387
|
+
TEST_METHOD(9) {
|
388
|
+
// If multiple matching processes exist, and all of them are at full capacity,
|
389
|
+
// and no more processes may be spawned,
|
390
|
+
// then asyncGet() will put the action on the group's wait queue.
|
391
|
+
// The process that first becomes not at full capacity will process the action.
|
392
|
+
|
393
|
+
// Spawn 2 processes and open 4 sessions.
|
394
|
+
Options options = createOptions();
|
395
|
+
options.appGroupName = "test";
|
396
|
+
options.minProcesses = 2;
|
397
|
+
pool->setMax(2);
|
398
|
+
GroupPtr group = pool->findOrCreateGroup(options);
|
399
|
+
dynamic_pointer_cast<DummySpawner>(group->spawner)->concurrency = 2;
|
400
|
+
|
401
|
+
vector<SessionPtr> sessions;
|
402
|
+
int expectedNumber = 1;
|
403
|
+
for (int i = 0; i < 4; i++) {
|
404
|
+
pool->asyncGet(options, callback);
|
405
|
+
EVENTUALLY(5,
|
406
|
+
result = number == expectedNumber;
|
407
|
+
);
|
408
|
+
expectedNumber++;
|
409
|
+
sessions.push_back(currentSession);
|
410
|
+
currentSession.reset();
|
411
|
+
}
|
412
|
+
EVENTUALLY(5,
|
413
|
+
result = pool->getProcessCount() == 2;
|
414
|
+
);
|
415
|
+
|
416
|
+
SuperGroupPtr superGroup = pool->superGroups.get("test");
|
417
|
+
ensure_equals(superGroup->groups[0]->getWaitlist.size(), 0u);
|
418
|
+
ensure(pool->atFullCapacity());
|
419
|
+
|
420
|
+
// Now try to open another session.
|
421
|
+
pool->asyncGet(options, callback);
|
422
|
+
ensure_equals("The get request has been put on the wait list",
|
423
|
+
pool->superGroups.get("test")->groups[0]->getWaitlist.size(), 1u);
|
424
|
+
|
425
|
+
// Close an existing session so that one process is no
|
426
|
+
// longer at full capacity.
|
427
|
+
sessions[0].reset();
|
428
|
+
ensure_equals("The get request has been removed from the wait list",
|
429
|
+
pool->superGroups.get("test")->groups[0]->getWaitlist.size(), 0u);
|
430
|
+
ensure(pool->atFullCapacity());
|
431
|
+
}
|
432
|
+
|
433
|
+
TEST_METHOD(10) {
|
434
|
+
// If multiple matching processes exist, and all of them are at full capacity,
|
435
|
+
// and a new process may be spawned,
|
436
|
+
// then asyncGet() will put the action on the group's wait queue and spawn the
|
437
|
+
// new process.
|
438
|
+
// The process that first becomes not at full capacity
|
439
|
+
// or the newly spawned process
|
440
|
+
// will process the action, whichever is earlier.
|
441
|
+
// Here we test the case where an existing process is earlier.
|
442
|
+
|
443
|
+
// Spawn 2 processes and open 4 sessions.
|
444
|
+
Options options = createOptions();
|
445
|
+
options.minProcesses = 2;
|
446
|
+
pool->setMax(3);
|
447
|
+
GroupPtr group = pool->findOrCreateGroup(options);
|
448
|
+
dynamic_pointer_cast<DummySpawner>(group->spawner)->concurrency = 2;
|
449
|
+
|
450
|
+
vector<SessionPtr> sessions;
|
451
|
+
int expectedNumber = 1;
|
452
|
+
for (int i = 0; i < 4; i++) {
|
453
|
+
pool->asyncGet(options, callback);
|
454
|
+
EVENTUALLY(5,
|
455
|
+
result = number == expectedNumber;
|
456
|
+
);
|
457
|
+
expectedNumber++;
|
458
|
+
sessions.push_back(currentSession);
|
459
|
+
currentSession.reset();
|
460
|
+
}
|
461
|
+
EVENTUALLY(5,
|
462
|
+
result = pool->getProcessCount() == 2;
|
463
|
+
);
|
464
|
+
|
465
|
+
// The next asyncGet() should spawn a new process and the action should be queued.
|
466
|
+
ScopedLock l(pool->syncher);
|
467
|
+
dynamic_pointer_cast<DummySpawner>(group->spawner)->spawnTime = 5000000;
|
468
|
+
pool->asyncGet(options, callback, false);
|
469
|
+
ensure(group->spawning());
|
470
|
+
ensure_equals(group->getWaitlist.size(), 1u);
|
471
|
+
l.unlock();
|
472
|
+
|
473
|
+
// Close one of the sessions. Now it will process the action.
|
474
|
+
ProcessPtr process = sessions[0]->getProcess();
|
475
|
+
sessions[0].reset();
|
476
|
+
ensure_equals(number, 5);
|
477
|
+
ensure_equals(currentSession->getProcess(), process);
|
478
|
+
ensure_equals(group->getWaitlist.size(), 0u);
|
479
|
+
ensure_equals(pool->getProcessCount(), 2u);
|
480
|
+
}
|
481
|
+
|
482
|
+
TEST_METHOD(11) {
|
483
|
+
// Here we test the case where the newly spawned process is earlier.
|
484
|
+
|
485
|
+
// Spawn 2 processes and open 4 sessions.
|
486
|
+
Options options = createOptions();
|
487
|
+
options.minProcesses = 2;
|
488
|
+
pool->setMax(3);
|
489
|
+
GroupPtr group = pool->findOrCreateGroup(options);
|
490
|
+
dynamic_pointer_cast<DummySpawner>(group->spawner)->concurrency = 2;
|
491
|
+
|
492
|
+
vector<SessionPtr> sessions;
|
493
|
+
int expectedNumber = 1;
|
494
|
+
for (int i = 0; i < 4; i++) {
|
495
|
+
pool->asyncGet(options, callback);
|
496
|
+
EVENTUALLY(5,
|
497
|
+
result = number == expectedNumber;
|
498
|
+
);
|
499
|
+
expectedNumber++;
|
500
|
+
sessions.push_back(currentSession);
|
501
|
+
currentSession.reset();
|
502
|
+
}
|
503
|
+
EVENTUALLY(5,
|
504
|
+
result = pool->getProcessCount() == 2;
|
505
|
+
);
|
506
|
+
|
507
|
+
// The next asyncGet() should spawn a new process. After it's done
|
508
|
+
// spawning it will process the action.
|
509
|
+
pool->asyncGet(options, callback);
|
510
|
+
EVENTUALLY(5,
|
511
|
+
result = pool->getProcessCount() == 3;
|
512
|
+
);
|
513
|
+
EVENTUALLY(5,
|
514
|
+
result = number == 5;
|
515
|
+
);
|
516
|
+
ensure_equals(currentSession->getProcess()->pid, 3);
|
517
|
+
ensure_equals(group->getWaitlist.size(), 0u);
|
518
|
+
}
|
519
|
+
|
520
|
+
|
521
|
+
/*********** Test asyncGet() behavior on multiple SuperGroups,
|
522
|
+
each with a single Group ***********/
|
523
|
+
|
524
|
+
TEST_METHOD(20) {
|
525
|
+
// If the pool is full, and one tries to asyncGet() from a nonexistant group,
|
526
|
+
// then it will kill the oldest idle process and spawn a new process.
|
527
|
+
Options options = createOptions();
|
528
|
+
pool->setMax(2);
|
529
|
+
|
530
|
+
// Get from /foo and close its session immediately.
|
531
|
+
options.appRoot = "/foo";
|
532
|
+
pool->asyncGet(options, callback);
|
533
|
+
EVENTUALLY(5,
|
534
|
+
result = number == 1;
|
535
|
+
);
|
536
|
+
ProcessPtr process1 = currentSession->getProcess();
|
537
|
+
GroupPtr group1 = process1->getGroup();
|
538
|
+
SuperGroupPtr superGroup1 = group1->getSuperGroup();
|
539
|
+
currentSession.reset();
|
540
|
+
|
541
|
+
// Get from /bar and keep its session open.
|
542
|
+
options.appRoot = "/bar";
|
543
|
+
pool->asyncGet(options, callback);
|
544
|
+
EVENTUALLY(5,
|
545
|
+
result = number == 2;
|
546
|
+
);
|
547
|
+
SessionPtr session2 = currentSession;
|
548
|
+
currentSession.reset();
|
549
|
+
|
550
|
+
// Get from /baz. The process for /foo should be killed now.
|
551
|
+
options.appRoot = "/baz";
|
552
|
+
pool->asyncGet(options, callback);
|
553
|
+
EVENTUALLY(5,
|
554
|
+
result = number == 3;
|
555
|
+
);
|
556
|
+
|
557
|
+
ensure_equals(pool->getProcessCount(), 2u);
|
558
|
+
ensure(!superGroup1->detached());
|
559
|
+
ensure_equals(superGroup1->getProcessCount(), 0u);
|
560
|
+
}
|
561
|
+
|
562
|
+
TEST_METHOD(21) {
|
563
|
+
// If the pool is full, and one tries to asyncGet() from a nonexistant group,
|
564
|
+
// and all existing processes are non-idle, then it will
|
565
|
+
// kill the oldest process and spawn a new process.
|
566
|
+
Options options = createOptions();
|
567
|
+
pool->setMax(2);
|
568
|
+
|
569
|
+
// Get from /foo and close its session immediately.
|
570
|
+
options.appRoot = "/foo";
|
571
|
+
pool->asyncGet(options, callback);
|
572
|
+
EVENTUALLY(5,
|
573
|
+
result = number == 1;
|
574
|
+
);
|
575
|
+
SessionPtr session1 = currentSession;
|
576
|
+
ProcessPtr process1 = currentSession->getProcess();
|
577
|
+
GroupPtr group1 = process1->getGroup();
|
578
|
+
SuperGroupPtr superGroup1 = group1->getSuperGroup();
|
579
|
+
|
580
|
+
// Get from /bar and keep its session open.
|
581
|
+
options.appRoot = "/bar";
|
582
|
+
pool->asyncGet(options, callback);
|
583
|
+
EVENTUALLY(5,
|
584
|
+
result = number == 2;
|
585
|
+
);
|
586
|
+
SessionPtr session2 = currentSession;
|
587
|
+
currentSession.reset();
|
588
|
+
|
589
|
+
// Get from /baz. The process for /foo should be killed now.
|
590
|
+
options.appRoot = "/baz";
|
591
|
+
pool->asyncGet(options, callback);
|
592
|
+
EVENTUALLY(5,
|
593
|
+
result = number == 3;
|
594
|
+
);
|
595
|
+
|
596
|
+
ensure_equals(pool->getProcessCount(), 2u);
|
597
|
+
ensure(!superGroup1->detached());
|
598
|
+
ensure_equals(superGroup1->getProcessCount(), 0u);
|
599
|
+
}
|
600
|
+
|
601
|
+
|
602
|
+
/*********** Test detachProcess() ***********/
|
603
|
+
|
604
|
+
TEST_METHOD(30) {
|
605
|
+
// detachProcess() detaches the process from the group.
|
606
|
+
Options options = createOptions();
|
607
|
+
options.appGroupName = "test";
|
608
|
+
options.minProcesses = 2;
|
609
|
+
pool->asyncGet(options, callback);
|
610
|
+
EVENTUALLY(5,
|
611
|
+
result = pool->getProcessCount() == 2;
|
612
|
+
);
|
613
|
+
EVENTUALLY(5,
|
614
|
+
result = number == 1;
|
615
|
+
);
|
616
|
+
|
617
|
+
pool->detachProcess(currentSession->getProcess());
|
618
|
+
ensure(currentSession->getProcess()->detached());
|
619
|
+
LockGuard l(pool->syncher);
|
620
|
+
ensure_equals(pool->superGroups.get("test")->defaultGroup->count, 1);
|
621
|
+
}
|
622
|
+
|
623
|
+
TEST_METHOD(31) {
|
624
|
+
// If the containing group had waiters on it, and detachProcess()
|
625
|
+
// detaches the only process in the group, then a new process
|
626
|
+
// is automatically spawned to handle the waiters.
|
627
|
+
Options options = createOptions();
|
628
|
+
options.appGroupName = "test";
|
629
|
+
pool->setMax(1);
|
630
|
+
pool->spawnerFactory->dummySpawnTime = 1000000;
|
631
|
+
|
632
|
+
pool->asyncGet(options, callback);
|
633
|
+
EVENTUALLY(5,
|
634
|
+
result = number == 1;
|
635
|
+
);
|
636
|
+
SessionPtr session1 = currentSession;
|
637
|
+
currentSession.reset();
|
638
|
+
|
639
|
+
pool->asyncGet(options, callback);
|
640
|
+
|
641
|
+
{
|
642
|
+
LockGuard l(pool->syncher);
|
643
|
+
ensure_equals(pool->superGroups.get("test")->defaultGroup->getWaitlist.size(), 1u);
|
644
|
+
}
|
645
|
+
|
646
|
+
pool->detachProcess(session1->getProcess());
|
647
|
+
{
|
648
|
+
LockGuard l(pool->syncher);
|
649
|
+
ensure(pool->superGroups.get("test")->defaultGroup->spawning());
|
650
|
+
ensure_equals(pool->superGroups.get("test")->defaultGroup->count, 0);
|
651
|
+
ensure_equals(pool->superGroups.get("test")->defaultGroup->getWaitlist.size(), 1u);
|
652
|
+
}
|
653
|
+
}
|
654
|
+
|
655
|
+
TEST_METHOD(32) {
|
656
|
+
// If the pool had waiters on it then detachProcess() will
|
657
|
+
// automatically create the SuperGroups that were requested
|
658
|
+
// by the waiters.
|
659
|
+
Options options = createOptions();
|
660
|
+
options.appGroupName = "test";
|
661
|
+
pool->setMax(1);
|
662
|
+
pool->spawnerFactory->dummySpawnTime = 30000;
|
663
|
+
|
664
|
+
// Begin spawning a process.
|
665
|
+
pool->asyncGet(options, callback);
|
666
|
+
ensure(pool->atFullCapacity());
|
667
|
+
|
668
|
+
// asyncGet() on another group should now put it on the waiting list.
|
669
|
+
Options options2 = createOptions();
|
670
|
+
options2.appGroupName = "test2";
|
671
|
+
pool->spawnerFactory->dummySpawnTime = 90000;
|
672
|
+
pool->asyncGet(options2, callback);
|
673
|
+
{
|
674
|
+
LockGuard l(pool->syncher);
|
675
|
+
ensure_equals(pool->getWaitlist.size(), 1u);
|
676
|
+
}
|
677
|
+
|
678
|
+
// Eventually the dummy process for "test" is now done spawning.
|
679
|
+
// We then detach it.
|
680
|
+
EVENTUALLY(5,
|
681
|
+
result = number == 1;
|
682
|
+
);
|
683
|
+
SessionPtr session1 = currentSession;
|
684
|
+
currentSession.reset();
|
685
|
+
pool->detachProcess(session1->getProcess());
|
686
|
+
{
|
687
|
+
LockGuard l(pool->syncher);
|
688
|
+
ensure(pool->superGroups.get("test2") != NULL);
|
689
|
+
ensure_equals(pool->getWaitlist.size(), 0u);
|
690
|
+
}
|
691
|
+
}
|
692
|
+
|
693
|
+
TEST_METHOD(33) {
|
694
|
+
// A SuperGroup does not become garbage collectable
|
695
|
+
// after detaching all its processes.
|
696
|
+
Options options = createOptions();
|
697
|
+
pool->asyncGet(options, callback);
|
698
|
+
EVENTUALLY(5,
|
699
|
+
result = number == 1;
|
700
|
+
);
|
701
|
+
ProcessPtr process = currentSession->getProcess();
|
702
|
+
currentSession.reset();
|
703
|
+
SuperGroupPtr superGroup = process->getSuperGroup();
|
704
|
+
pool->detachProcess(process);
|
705
|
+
LockGuard l(pool->syncher);
|
706
|
+
ensure_equals(pool->superGroups.size(), 1u);
|
707
|
+
ensure(!superGroup->detached());
|
708
|
+
ensure(!superGroup->garbageCollectable());
|
709
|
+
}
|
710
|
+
|
711
|
+
|
712
|
+
/*********** Test disabling and enabling processes ***********/
|
713
|
+
|
714
|
+
TEST_METHOD(40) {
|
715
|
+
// Disabling a process under idle conditions should succeed immediately.
|
716
|
+
/*
|
717
|
+
Options options = createOptions();
|
718
|
+
options.minProcesses = 2;
|
719
|
+
options.noop = true;
|
720
|
+
pool->asyncGet(options, callback);
|
721
|
+
EVENTUALLY(5,
|
722
|
+
result = number == 1;
|
723
|
+
);
|
724
|
+
EVENTUALLY(5,
|
725
|
+
result = pool->getProcessCount() == 2;
|
726
|
+
);
|
727
|
+
|
728
|
+
options.minProcesses = 0;
|
729
|
+
options.noop = false;
|
730
|
+
vector<ProcessPtr> processes = pool->getProcesses();
|
731
|
+
ensure_equals(processes, );
|
732
|
+
*/
|
733
|
+
}
|
734
|
+
|
735
|
+
// Disabling the sole process in a group should trigger a new process spawn.
|
736
|
+
// Disabling should succeed after the new process has been spawned.
|
737
|
+
|
738
|
+
// Duppose that a previous disable command triggered a new process spawn,
|
739
|
+
// and the spawn fails. Then the processes which were marked as 'disabled'
|
740
|
+
// should be marked 'enabled' again, and the callbacks for the previous
|
741
|
+
// disable commands should be called.
|
742
|
+
|
743
|
+
// asyncGet() should not select a process that's being disabled, unless
|
744
|
+
// it's the only process in the group.
|
745
|
+
|
746
|
+
// Disabling a process that's already being disabled should result in the
|
747
|
+
// callback being called after disabling is done.
|
748
|
+
|
749
|
+
// Enabling a process that's being disabled should immediately mark the process
|
750
|
+
// as being enabled and should call all the queued disable command callbacks.
|
751
|
+
|
752
|
+
// Enabling a process that's disabled works.
|
753
|
+
|
754
|
+
|
755
|
+
/*********** Other tests ***********/
|
756
|
+
|
757
|
+
TEST_METHOD(50) {
|
758
|
+
// The pool is considered to be at full capacity if and only
|
759
|
+
// if all SuperGroups are at full capacity.
|
760
|
+
Options options = createOptions();
|
761
|
+
Options options2 = createOptions();
|
762
|
+
options2.appGroupName = "test";
|
763
|
+
|
764
|
+
pool->setMax(2);
|
765
|
+
pool->asyncGet(options, callback);
|
766
|
+
EVENTUALLY(5,
|
767
|
+
result = number == 1;
|
768
|
+
);
|
769
|
+
|
770
|
+
pool->asyncGet(options2, callback);
|
771
|
+
EVENTUALLY(5,
|
772
|
+
result = number == 2;
|
773
|
+
);
|
774
|
+
|
775
|
+
ensure_equals(pool->getProcessCount(), 2u);
|
776
|
+
ensure(pool->atFullCapacity());
|
777
|
+
pool->detachSuperGroup(pool->getSuperGroup("test"));
|
778
|
+
ensure(!pool->atFullCapacity());
|
779
|
+
}
|
780
|
+
|
781
|
+
TEST_METHOD(51) {
|
782
|
+
// If the pool is at full capacity, then increasing 'max' will cause
|
783
|
+
// new processes to be spawned. Any queued get requests are processed
|
784
|
+
// as those new processes become available or as existing processes
|
785
|
+
// become available.
|
786
|
+
Options options = createOptions();
|
787
|
+
retainSessions = true;
|
788
|
+
pool->setMax(1);
|
789
|
+
|
790
|
+
pool->asyncGet(options, callback);
|
791
|
+
pool->asyncGet(options, callback);
|
792
|
+
pool->asyncGet(options, callback);
|
793
|
+
EVENTUALLY(5,
|
794
|
+
result = number == 1;
|
795
|
+
);
|
796
|
+
|
797
|
+
pool->setMax(4);
|
798
|
+
EVENTUALLY(5,
|
799
|
+
result = number == 3;
|
800
|
+
);
|
801
|
+
ensure_equals(pool->getProcessCount(), 3u);
|
802
|
+
}
|
803
|
+
|
804
|
+
TEST_METHOD(52) {
|
805
|
+
// Each spawned process has a GUPID, which can be looked up
|
806
|
+
// through findProcessByGupid().
|
807
|
+
Options options = createOptions();
|
808
|
+
pool->asyncGet(options, callback);
|
809
|
+
EVENTUALLY(5,
|
810
|
+
result = number == 1;
|
811
|
+
);
|
812
|
+
string gupid = currentSession->getProcess()->gupid;
|
813
|
+
ensure(!gupid.empty());
|
814
|
+
ensure_equals(currentSession->getProcess(), pool->findProcessByGupid(gupid));
|
815
|
+
}
|
816
|
+
|
817
|
+
TEST_METHOD(53) {
|
818
|
+
// findProcessByGupid() returns a NULL pointer if there is
|
819
|
+
// no matching process.
|
820
|
+
ensure(pool->findProcessByGupid("none") == NULL);
|
821
|
+
}
|
822
|
+
|
823
|
+
TEST_METHOD(54) {
|
824
|
+
// Test process idle cleaning.
|
825
|
+
Options options = createOptions();
|
826
|
+
retainSessions = true;
|
827
|
+
pool->setMaxIdleTime(50000);
|
828
|
+
pool->asyncGet(options, callback);
|
829
|
+
pool->asyncGet(options, callback);
|
830
|
+
EVENTUALLY(2,
|
831
|
+
result = number == 2;
|
832
|
+
);
|
833
|
+
ensure_equals(pool->getProcessCount(), 2u);
|
834
|
+
|
835
|
+
currentSession.reset();
|
836
|
+
sessions.pop_back();
|
837
|
+
|
838
|
+
// One of the processes still has a session open and should
|
839
|
+
// not be idle cleaned.
|
840
|
+
EVENTUALLY(2,
|
841
|
+
result = pool->getProcessCount() == 1;
|
842
|
+
);
|
843
|
+
SHOULD_NEVER_HAPPEN(150,
|
844
|
+
result = pool->getProcessCount() == 0;
|
845
|
+
);
|
846
|
+
|
847
|
+
// It shouldn't clean more processes than minInstances allows.
|
848
|
+
sessions.clear();
|
849
|
+
SHOULD_NEVER_HAPPEN(150,
|
850
|
+
result = pool->getProcessCount() == 0;
|
851
|
+
);
|
852
|
+
}
|
853
|
+
|
854
|
+
TEST_METHOD(55) {
|
855
|
+
// Test spawner idle cleaning.
|
856
|
+
Options options = createOptions();
|
857
|
+
options.appGroupName = "test1";
|
858
|
+
Options options2 = createOptions();
|
859
|
+
options2.appGroupName = "test2";
|
860
|
+
|
861
|
+
retainSessions = true;
|
862
|
+
pool->setMaxIdleTime(50000);
|
863
|
+
pool->asyncGet(options, callback);
|
864
|
+
pool->asyncGet(options2, callback);
|
865
|
+
EVENTUALLY(2,
|
866
|
+
result = number == 2;
|
867
|
+
);
|
868
|
+
ensure_equals(pool->getProcessCount(), 2u);
|
869
|
+
|
870
|
+
EVENTUALLY(2,
|
871
|
+
SpawnerPtr spawner = pool->getSuperGroup("test1")->defaultGroup->spawner;
|
872
|
+
result = static_pointer_cast<DummySpawner>(spawner)->cleanCount >= 1;
|
873
|
+
);
|
874
|
+
EVENTUALLY(2,
|
875
|
+
SpawnerPtr spawner = pool->getSuperGroup("test2")->defaultGroup->spawner;
|
876
|
+
result = static_pointer_cast<DummySpawner>(spawner)->cleanCount >= 1;
|
877
|
+
);
|
878
|
+
}
|
879
|
+
|
880
|
+
TEST_METHOD(56) {
|
881
|
+
// It should restart the app if restart.txt is created or updated.
|
882
|
+
TempDirCopy dir("stub/wsgi", "tmp.wsgi");
|
883
|
+
Options options = createOptions();
|
884
|
+
options.appRoot = "tmp.wsgi";
|
885
|
+
options.appType = "wsgi";
|
886
|
+
options.spawnMethod = "direct";
|
887
|
+
ProcessPtr process;
|
888
|
+
pool->setMax(1);
|
889
|
+
|
890
|
+
// Send normal request.
|
891
|
+
ensure_equals(sendRequest(options, "/"), "hello <b>world</b>");
|
892
|
+
|
893
|
+
// Modify application; it shouldn't have effect yet.
|
894
|
+
writeFile("tmp.wsgi/passenger_wsgi.py",
|
895
|
+
"def application(env, start_response):\n"
|
896
|
+
" start_response('200 OK', [('Content-Type', 'text/html')])\n"
|
897
|
+
" return ['restarted']\n");
|
898
|
+
ensure_equals(sendRequest(options, "/"), "hello <b>world</b>");
|
899
|
+
|
900
|
+
// Create restart.txt and send request again. The change should now be activated.
|
901
|
+
touchFile("tmp.wsgi/tmp/restart.txt", 1);
|
902
|
+
ensure_equals(sendRequest(options, "/"), "restarted");
|
903
|
+
|
904
|
+
// Modify application again; it shouldn't have effect yet.
|
905
|
+
writeFile("tmp.wsgi/passenger_wsgi.py",
|
906
|
+
"def application(env, start_response):\n"
|
907
|
+
" start_response('200 OK', [('Content-Type', 'text/html')])\n"
|
908
|
+
" return ['restarted 2']\n");
|
909
|
+
ensure_equals(sendRequest(options, "/"), "restarted");
|
910
|
+
|
911
|
+
// Touch restart.txt and send request again. The change should now be activated.
|
912
|
+
touchFile("tmp.wsgi/tmp/restart.txt", 2);
|
913
|
+
ensure_equals(sendRequest(options, "/"), "restarted 2");
|
914
|
+
}
|
915
|
+
|
916
|
+
TEST_METHOD(57) {
|
917
|
+
// Test spawn exceptions.
|
918
|
+
TempDirCopy dir("stub/wsgi", "tmp.wsgi");
|
919
|
+
Options options = createOptions();
|
920
|
+
options.appRoot = "tmp.wsgi";
|
921
|
+
options.appType = "wsgi";
|
922
|
+
options.spawnMethod = "direct";
|
923
|
+
spawnerFactory->forwardStderr = false;
|
924
|
+
|
925
|
+
writeFile("tmp.wsgi/passenger_wsgi.py",
|
926
|
+
"import sys\n"
|
927
|
+
"sys.stderr.write('Something went wrong!')\n"
|
928
|
+
"exit(1)\n");
|
929
|
+
pool->asyncGet(options, callback);
|
930
|
+
EVENTUALLY(5,
|
931
|
+
result = number == 1;
|
932
|
+
);
|
933
|
+
|
934
|
+
ensure(currentException != NULL);
|
935
|
+
shared_ptr<SpawnException> e = dynamic_pointer_cast<SpawnException>(currentException);
|
936
|
+
ensure_equals(e->getErrorPage(), "Something went wrong!");
|
937
|
+
}
|
938
|
+
|
939
|
+
TEST_METHOD(58) {
|
940
|
+
// If a process fails to spawn, then it stops trying to spawn minProcesses processes.
|
941
|
+
TempDirCopy dir("stub/wsgi", "tmp.wsgi");
|
942
|
+
Options options = createOptions();
|
943
|
+
options.appRoot = "tmp.wsgi";
|
944
|
+
options.appType = "wsgi";
|
945
|
+
options.spawnMethod = "direct";
|
946
|
+
options.minProcesses = 4;
|
947
|
+
spawnerFactory->forwardStderr = false;
|
948
|
+
|
949
|
+
writeFile("tmp.wsgi/counter", "0");
|
950
|
+
// Our application starts successfully the first two times,
|
951
|
+
// and fails all the other times.
|
952
|
+
writeFile("tmp.wsgi/passenger_wsgi.py",
|
953
|
+
"import sys\n"
|
954
|
+
|
955
|
+
"def application(env, start_response):\n"
|
956
|
+
" pass\n"
|
957
|
+
|
958
|
+
"counter = int(open('counter', 'r').read())\n"
|
959
|
+
"f = open('counter', 'w')\n"
|
960
|
+
"f.write(str(counter + 1))\n"
|
961
|
+
"f.close()\n"
|
962
|
+
"if counter >= 2:\n"
|
963
|
+
" sys.stderr.write('Something went wrong!')\n"
|
964
|
+
" exit(1)\n");
|
965
|
+
|
966
|
+
pool->asyncGet(options, callback);
|
967
|
+
EVENTUALLY(5,
|
968
|
+
result = number == 1;
|
969
|
+
);
|
970
|
+
EVENTUALLY(5,
|
971
|
+
result = pool->getProcessCount() == 2;
|
972
|
+
);
|
973
|
+
EVENTUALLY(2,
|
974
|
+
result = !pool->getSuperGroup("tmp.wsgi")->defaultGroup->spawning();
|
975
|
+
);
|
976
|
+
SHOULD_NEVER_HAPPEN(500,
|
977
|
+
result = pool->getProcessCount() > 2;
|
978
|
+
);
|
979
|
+
}
|
980
|
+
|
981
|
+
TEST_METHOD(59) {
|
982
|
+
// It removes the process from the pool if session->initiate() fails.
|
983
|
+
Options options = createOptions();
|
984
|
+
options.appRoot = "stub/wsgi";
|
985
|
+
options.appType = "wsgi";
|
986
|
+
options.spawnMethod = "direct";
|
987
|
+
|
988
|
+
pool->asyncGet(options, callback);
|
989
|
+
EVENTUALLY(5,
|
990
|
+
result = number == 1;
|
991
|
+
);
|
992
|
+
pid_t pid = currentSession->getPid();
|
993
|
+
|
994
|
+
kill(pid, SIGTERM);
|
995
|
+
// Wait until process is gone.
|
996
|
+
EVENTUALLY(5,
|
997
|
+
result = kill(pid, 0) == -1 && (errno == ESRCH || errno == EPERM || errno == ECHILD);
|
998
|
+
);
|
999
|
+
|
1000
|
+
try {
|
1001
|
+
currentSession->initiate();
|
1002
|
+
fail("Initiate is supposed to fail");
|
1003
|
+
} catch (const SystemException &e) {
|
1004
|
+
ensure_equals(e.code(), ECONNREFUSED);
|
1005
|
+
}
|
1006
|
+
ensure_equals(pool->getProcessCount(), 0u);
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
TEST_METHOD(60) {
|
1010
|
+
// When a process has become idle, and there are waiters on the pool,
|
1011
|
+
// consider detaching it in order to satisfy a waiter.
|
1012
|
+
Options options1 = createOptions();
|
1013
|
+
Options options2 = createOptions();
|
1014
|
+
options2.appRoot = "stub/wsgi";
|
1015
|
+
options2.allowTrashingNonIdleProcesses = false;
|
1016
|
+
|
1017
|
+
retainSessions = true;
|
1018
|
+
pool->setMax(2);
|
1019
|
+
pool->asyncGet(options1, callback);
|
1020
|
+
pool->asyncGet(options1, callback);
|
1021
|
+
EVENTUALLY(3,
|
1022
|
+
result = pool->getProcessCount() == 2;
|
1023
|
+
);
|
1024
|
+
pool->asyncGet(options2, callback);
|
1025
|
+
ensure_equals(pool->getWaitlist.size(), 1u);
|
1026
|
+
ensure_equals(number, 2);
|
1027
|
+
|
1028
|
+
currentSession.reset();
|
1029
|
+
sessions.pop_front();
|
1030
|
+
EVENTUALLY(3,
|
1031
|
+
result = number == 3;
|
1032
|
+
);
|
1033
|
+
ensure_equals(pool->getProcessCount(), 2u);
|
1034
|
+
SuperGroupPtr superGroup1 = pool->superGroups.get("stub/rack");
|
1035
|
+
SuperGroupPtr superGroup2 = pool->superGroups.get("stub/rack");
|
1036
|
+
ensure_equals(superGroup1->defaultGroup->count, 1);
|
1037
|
+
ensure_equals(superGroup2->defaultGroup->count, 1);
|
1038
|
+
}
|
1039
|
+
|
1040
|
+
TEST_METHOD(61) {
|
1041
|
+
// A process is detached after processing maxRequests sessions.
|
1042
|
+
{
|
1043
|
+
Ticket ticket;
|
1044
|
+
Options options = createOptions();
|
1045
|
+
options.maxRequests = 5;
|
1046
|
+
pool->setMax(1);
|
1047
|
+
pool->get(options, &ticket).reset();
|
1048
|
+
|
1049
|
+
vector<ProcessPtr> processes = pool->getProcesses();
|
1050
|
+
ensure_equals(processes.size(), 1u);
|
1051
|
+
pid_t origPid = processes[0]->pid;
|
1052
|
+
|
1053
|
+
for (int i = 0; i < 3; i++) {
|
1054
|
+
pool->get(options, &ticket).reset();
|
1055
|
+
processes = pool->getProcesses();
|
1056
|
+
ensure_equals(processes.size(), 1u);
|
1057
|
+
ensure_equals(processes[0]->pid, origPid);
|
1058
|
+
}
|
1059
|
+
|
1060
|
+
pool->get(options, &ticket).reset();
|
1061
|
+
}
|
1062
|
+
EVENTUALLY(2,
|
1063
|
+
result = pool->getProcessCount() == 0;
|
1064
|
+
);
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
TEST_METHOD(62) {
|
1068
|
+
// If we restart while spawning is in progress, then the spawn
|
1069
|
+
// loop will exit as soon as it has detected that we're restarting.
|
1070
|
+
TempDirCopy dir("stub/wsgi", "tmp.wsgi");
|
1071
|
+
spawnerFactory->dummySpawnTime = 20000;
|
1072
|
+
spawnerFactory->dummySpawnerCreationSleepTime = 100000;
|
1073
|
+
|
1074
|
+
Options options = createOptions();
|
1075
|
+
options.appRoot = "tmp.wsgi";
|
1076
|
+
options.minProcesses = 3;
|
1077
|
+
|
1078
|
+
// Trigger spawn loop. The spawn loop itself won't take longer than 3*20=60 msec.
|
1079
|
+
pool->findOrCreateGroup(options);
|
1080
|
+
ScopedLock l(pool->syncher);
|
1081
|
+
pool->asyncGet(options, callback, false);
|
1082
|
+
// Wait until spawn loop tries to grab the lock.
|
1083
|
+
EVENTUALLY(3,
|
1084
|
+
LockGuard l2(pool->debugSyncher);
|
1085
|
+
result = pool->spawnLoopIteration == 1;
|
1086
|
+
);
|
1087
|
+
l.unlock();
|
1088
|
+
|
1089
|
+
// At this point, the spawn loop is about to attach its first spawned
|
1090
|
+
// process to the group. We wait until it has succeeded doing so.
|
1091
|
+
// Remaining maximum time in the spawn loop: 2*20=40 msec.
|
1092
|
+
EVENTUALLY2(200, 0,
|
1093
|
+
result = pool->getProcessCount() == 1;
|
1094
|
+
);
|
1095
|
+
|
1096
|
+
// Trigger restart. It will immediately detach the sole process in the pool,
|
1097
|
+
// and it will finish after approximately 100 msec,
|
1098
|
+
// allowing the spawn loop to detect that the restart flag is true.
|
1099
|
+
touchFile("tmp.wsgi/tmp/restart.txt");
|
1100
|
+
pool->asyncGet(options, callback);
|
1101
|
+
ensure_equals("(1)", pool->getProcessCount(), 0u);
|
1102
|
+
|
1103
|
+
// The spawn loop will succeed at spawning the second process.
|
1104
|
+
// Upon attaching it, it should detect the restart the stop,
|
1105
|
+
// so that it never spawns the third process.
|
1106
|
+
SHOULD_NEVER_HAPPEN(300,
|
1107
|
+
LockGuard l2(pool->debugSyncher);
|
1108
|
+
result = pool->spawnLoopIteration > 2;
|
1109
|
+
);
|
1110
|
+
ensure_equals("(2)", pool->getProcessCount(), 1u);
|
1111
|
+
}
|
1112
|
+
|
1113
|
+
TEST_METHOD(63) {
|
1114
|
+
// If a get() request comes in while the restart is in progress, then
|
1115
|
+
// that get() request will be put into the get waiters list, which will
|
1116
|
+
// be processed after spawning is done.
|
1117
|
+
|
1118
|
+
// Spawn 2 processes.
|
1119
|
+
TempDirCopy dir("stub/wsgi", "tmp.wsgi");
|
1120
|
+
Options options = createOptions();
|
1121
|
+
options.appRoot = "tmp.wsgi";
|
1122
|
+
options.minProcesses = 2;
|
1123
|
+
pool->asyncGet(options, callback);
|
1124
|
+
EVENTUALLY(2,
|
1125
|
+
result = pool->getProcessCount() == 2;
|
1126
|
+
);
|
1127
|
+
|
1128
|
+
// Trigger a restart. The creation of the new spawner should take a while.
|
1129
|
+
spawnerFactory->dummySpawnerCreationSleepTime = 20000;
|
1130
|
+
touchFile("tmp.wsgi/tmp/restart.txt");
|
1131
|
+
pool->asyncGet(options, callback);
|
1132
|
+
GroupPtr group = pool->findOrCreateGroup(options);
|
1133
|
+
ensure_equals(pool->getProcessCount(), 0u);
|
1134
|
+
ensure_equals(group->getWaitlist.size(), 1u);
|
1135
|
+
|
1136
|
+
// Now that the restart is in progress, perform a get().
|
1137
|
+
pool->asyncGet(options, callback);
|
1138
|
+
ensure_equals(group->getWaitlist.size(), 2u);
|
1139
|
+
EVENTUALLY(2,
|
1140
|
+
result = number == 3;
|
1141
|
+
);
|
1142
|
+
ensure_equals("The restart function respects minProcesses",
|
1143
|
+
pool->getProcessCount(), 2u);
|
1144
|
+
}
|
1145
|
+
|
1146
|
+
TEST_METHOD(64) {
|
1147
|
+
// If a process fails to spawn, it sends a SpawnException result to all get waiters.
|
1148
|
+
TempDirCopy dir("stub/wsgi", "tmp.wsgi");
|
1149
|
+
Options options = createOptions();
|
1150
|
+
options.appRoot = "tmp.wsgi";
|
1151
|
+
options.appType = "wsgi";
|
1152
|
+
options.spawnMethod = "direct";
|
1153
|
+
spawnerFactory->forwardStderr = false;
|
1154
|
+
pool->setMax(1);
|
1155
|
+
|
1156
|
+
writeFile("tmp.wsgi/passenger_wsgi.py",
|
1157
|
+
"import os, time, sys\n"
|
1158
|
+
"\n"
|
1159
|
+
"def file_exists(filename):\n"
|
1160
|
+
" try:\n"
|
1161
|
+
" os.stat(filename)\n"
|
1162
|
+
" return True\n"
|
1163
|
+
" except OSError:\n"
|
1164
|
+
" return False\n"
|
1165
|
+
"\n"
|
1166
|
+
"f = open('spawned.txt', 'w')\n"
|
1167
|
+
"f.write(str(os.getpid()))\n"
|
1168
|
+
"f.close()\n"
|
1169
|
+
"while not file_exists('continue.txt'):\n"
|
1170
|
+
" time.sleep(0.05)\n"
|
1171
|
+
"sys.stderr.write('Something went wrong!')\n"
|
1172
|
+
"exit(1)\n");
|
1173
|
+
|
1174
|
+
retainSessions = true;
|
1175
|
+
pool->asyncGet(options, callback);
|
1176
|
+
pool->asyncGet(options, callback);
|
1177
|
+
pool->asyncGet(options, callback);
|
1178
|
+
pool->asyncGet(options, callback);
|
1179
|
+
|
1180
|
+
EVENTUALLY(5,
|
1181
|
+
result = fileExists("tmp.wsgi/spawned.txt");
|
1182
|
+
);
|
1183
|
+
usleep(20000);
|
1184
|
+
writeFile("tmp.wsgi/passenger_wsgi.py", readAll("stub/wsgi/passenger_wsgi.py"));
|
1185
|
+
pid_t pid = (pid_t) stringToLL(readAll("tmp.wsgi/spawned.txt"));
|
1186
|
+
kill(pid, SIGTERM);
|
1187
|
+
EVENTUALLY(5,
|
1188
|
+
result = number == 4;
|
1189
|
+
);
|
1190
|
+
ensure_equals(pool->getProcessCount(), 0u);
|
1191
|
+
ensure(sessions.empty());
|
1192
|
+
}
|
1193
|
+
|
1194
|
+
TEST_METHOD(65) {
|
1195
|
+
// If a process fails to spawn, the existing processes
|
1196
|
+
// are kept alive.
|
1197
|
+
TempDirCopy dir("stub/wsgi", "tmp.wsgi");
|
1198
|
+
Options options = createOptions();
|
1199
|
+
options.appRoot = "tmp.wsgi";
|
1200
|
+
options.appType = "wsgi";
|
1201
|
+
options.spawnMethod = "direct";
|
1202
|
+
options.minProcesses = 2;
|
1203
|
+
spawnerFactory->forwardStderr = false;
|
1204
|
+
|
1205
|
+
// Spawn 2 processes.
|
1206
|
+
retainSessions = true;
|
1207
|
+
pool->asyncGet(options, callback);
|
1208
|
+
pool->asyncGet(options, callback);
|
1209
|
+
EVENTUALLY(5,
|
1210
|
+
result = number == 2;
|
1211
|
+
);
|
1212
|
+
ensure_equals(pool->getProcessCount(), 2u);
|
1213
|
+
|
1214
|
+
// Mess up the application and spawn a new one.
|
1215
|
+
writeFile("tmp.wsgi/passenger_wsgi.py",
|
1216
|
+
"import sys\n"
|
1217
|
+
"sys.stderr.write('Something went wrong!')\n"
|
1218
|
+
"exit(1)\n");
|
1219
|
+
try {
|
1220
|
+
Ticket ticket;
|
1221
|
+
currentSession = pool->get(options, &ticket);
|
1222
|
+
fail("SpawnException expected");
|
1223
|
+
} catch (const SpawnException &) {
|
1224
|
+
ensure_equals(pool->getProcessCount(), 2u);
|
1225
|
+
}
|
1226
|
+
}
|
1227
|
+
|
1228
|
+
// Persistent connections.
|
1229
|
+
// If one closes the session before it has reached EOF, and process's maximum concurrency
|
1230
|
+
// has already been reached, then the pool should ping the process so that it can detect
|
1231
|
+
// when the session's connection has been released by the app.
|
1232
|
+
|
1233
|
+
/*****************************/
|
1234
|
+
}
|