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
@@ -1,108 +0,0 @@
|
|
1
|
-
# Phusion Passenger - http://www.modrails.com/
|
2
|
-
# Copyright (c) 2010 Phusion
|
3
|
-
#
|
4
|
-
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
5
|
-
#
|
6
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
-
# of this software and associated documentation files (the "Software"), to deal
|
8
|
-
# in the Software without restriction, including without limitation the rights
|
9
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
-
# copies of the Software, and to permit persons to whom the Software is
|
11
|
-
# furnished to do so, subject to the following conditions:
|
12
|
-
#
|
13
|
-
# The above copyright notice and this permission notice shall be included in
|
14
|
-
# all copies or substantial portions of the Software.
|
15
|
-
#
|
16
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
-
# THE SOFTWARE.
|
23
|
-
|
24
|
-
require 'socket'
|
25
|
-
require 'phusion_passenger/app_process'
|
26
|
-
require 'phusion_passenger/message_channel'
|
27
|
-
require 'phusion_passenger/public_api'
|
28
|
-
require 'phusion_passenger/utils'
|
29
|
-
require 'phusion_passenger/utils/tmpdir'
|
30
|
-
require 'phusion_passenger/native_support'
|
31
|
-
|
32
|
-
module PhusionPassenger
|
33
|
-
module WSGI
|
34
|
-
|
35
|
-
# Class for spawning WSGI applications.
|
36
|
-
class ApplicationSpawner
|
37
|
-
include Utils
|
38
|
-
REQUEST_HANDLER = File.expand_path(File.dirname(__FILE__) + "/request_handler.py")
|
39
|
-
|
40
|
-
def self.spawn_application(*args)
|
41
|
-
@@instance ||= ApplicationSpawner.new
|
42
|
-
@@instance.spawn_application(*args)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Spawn an instance of the given WSGI application. When successful, an
|
46
|
-
# Application object will be returned, which represents the spawned
|
47
|
-
# application.
|
48
|
-
#
|
49
|
-
# Raises:
|
50
|
-
# - AppInitError: The WSGI application raised an exception or called
|
51
|
-
# exit() during startup.
|
52
|
-
# - SystemCallError, IOError, SocketError: Something went wrong.
|
53
|
-
def spawn_application(options)
|
54
|
-
a, b = UNIXSocket.pair
|
55
|
-
pid = safe_fork(self.class.to_s, true) do
|
56
|
-
a.close
|
57
|
-
|
58
|
-
file_descriptors_to_leave_open = [0, 1, 2, b.fileno]
|
59
|
-
NativeSupport.close_all_file_descriptors(file_descriptors_to_leave_open)
|
60
|
-
close_all_io_objects_for_fds(file_descriptors_to_leave_open)
|
61
|
-
|
62
|
-
run(MessageChannel.new(b), options)
|
63
|
-
end
|
64
|
-
b.close
|
65
|
-
Process.waitpid(pid) rescue nil
|
66
|
-
|
67
|
-
channel = MessageChannel.new(a)
|
68
|
-
return AppProcess.read_from_channel(channel)
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
def run(channel, options)
|
73
|
-
$0 = "WSGI: #{options['app_group_name']}"
|
74
|
-
prepare_app_process("passenger_wsgi.py", options)
|
75
|
-
ENV['WSGI_ENV'] = options['environment']
|
76
|
-
|
77
|
-
if defined?(NativeSupport)
|
78
|
-
unix_path_max = NativeSupport::UNIX_PATH_MAX
|
79
|
-
else
|
80
|
-
unix_path_max = 100
|
81
|
-
end
|
82
|
-
|
83
|
-
socket_file = "#{passenger_tmpdir}/backends/wsgi.#{Process.pid}.#{rand 10000000}"
|
84
|
-
socket_file = socket_file.slice(0, unix_path_max - 1)
|
85
|
-
server = UNIXServer.new(socket_file)
|
86
|
-
begin
|
87
|
-
File.chmod(0666, socket_file)
|
88
|
-
reader, writer = IO.pipe
|
89
|
-
app_process = AppProcess.new(options["app_root"], Process.pid, writer,
|
90
|
-
:main => [socket_file, 'unix'])
|
91
|
-
app_process.write_to_channel(channel)
|
92
|
-
writer.close
|
93
|
-
channel.close
|
94
|
-
|
95
|
-
NativeSupport.close_all_file_descriptors([0, 1, 2, server.fileno,
|
96
|
-
reader.fileno])
|
97
|
-
exec(REQUEST_HANDLER, socket_file, server.fileno.to_s,
|
98
|
-
reader.fileno.to_s)
|
99
|
-
rescue
|
100
|
-
server.close
|
101
|
-
File.unlink(socket_file)
|
102
|
-
raise
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
end # module WSGI
|
108
|
-
end # module PhusionPassenger
|
data/test/config.yml.example
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
### This file contains system-specific configuration options that the test suite needs.
|
2
|
-
### Please customize it for your system.
|
3
|
-
|
4
|
-
# These are the usernames and group names of normal, non-administrator
|
5
|
-
# users and groups. Preferably, these are user and group accounts that
|
6
|
-
# are normally not used.
|
7
|
-
#
|
8
|
-
# These users and groups MUST be able to access this 'test' directory,
|
9
|
-
# otherwise the tests will fail.
|
10
|
-
|
11
|
-
### Good values for Linux and FreeBSD:
|
12
|
-
normal_user_1: games
|
13
|
-
normal_user_2: daemon
|
14
|
-
# Must not be "nobody".
|
15
|
-
default_user: man
|
16
|
-
# Must not be normal_user_1's primary group.
|
17
|
-
normal_group_1: daemon
|
18
|
-
# Must not be normal_user_2's primary group.
|
19
|
-
normal_group_2: man
|
20
|
-
# Must not be default_user's primary group. Must not be "nobody".
|
21
|
-
default_group: games
|
22
|
-
|
23
|
-
### Good values for OS X. Same restrictions apply.
|
24
|
-
# normal_user_1: _www
|
25
|
-
# normal_user_2: daemon
|
26
|
-
# default_user: _sandbox
|
27
|
-
# normal_group_1: daemon
|
28
|
-
# normal_group_2: _sandbox
|
29
|
-
# default_group: _www
|
30
|
-
|
31
|
-
# A nonexistant username, group name, user ID and group ID.
|
32
|
-
nonexistant_user: xxxxxxxxxxxxxxxxxxx
|
33
|
-
nonexistant_group: xxxxxxxxxxxxxxxxxxx
|
34
|
-
nonexistant_uid: 9999
|
35
|
-
nonexistant_gid: 9999
|
36
|
-
|
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
|
@@ -1,33 +0,0 @@
|
|
1
|
-
#include "TestSupport.h"
|
2
|
-
#include "ApplicationPool/Pool.h"
|
3
|
-
#include "Utils.h"
|
4
|
-
|
5
|
-
using namespace Passenger;
|
6
|
-
|
7
|
-
namespace tut {
|
8
|
-
struct ApplicationPool_PoolTest {
|
9
|
-
ServerInstanceDirPtr serverInstanceDir;
|
10
|
-
ServerInstanceDir::GenerationPtr generation;
|
11
|
-
ApplicationPool::Ptr pool, pool2;
|
12
|
-
|
13
|
-
ApplicationPool_PoolTest() {
|
14
|
-
createServerInstanceDirAndGeneration(serverInstanceDir, generation);
|
15
|
-
pool = ptr(new ApplicationPool::Pool("../helper-scripts/passenger-spawn-server", generation));
|
16
|
-
pool2 = pool;
|
17
|
-
}
|
18
|
-
|
19
|
-
ApplicationPool::Ptr newPoolConnection() {
|
20
|
-
return pool;
|
21
|
-
}
|
22
|
-
|
23
|
-
void reinitializeWithSpawnManager(AbstractSpawnManagerPtr spawnManager) {
|
24
|
-
pool = ptr(new ApplicationPool::Pool(spawnManager));
|
25
|
-
pool2 = pool;
|
26
|
-
}
|
27
|
-
};
|
28
|
-
|
29
|
-
DEFINE_TEST_GROUP(ApplicationPool_PoolTest);
|
30
|
-
|
31
|
-
#define USE_TEMPLATE
|
32
|
-
#include "ApplicationPool_PoolTestCases.cpp"
|
33
|
-
}
|
@@ -1,1029 +0,0 @@
|
|
1
|
-
#include <sys/types.h>
|
2
|
-
#include <sys/stat.h>
|
3
|
-
#include <unistd.h>
|
4
|
-
#include <cstring>
|
5
|
-
#include <cstdlib>
|
6
|
-
#include <cerrno>
|
7
|
-
#include <sys/types.h>
|
8
|
-
#include <signal.h>
|
9
|
-
#include <utime.h>
|
10
|
-
|
11
|
-
/**
|
12
|
-
* This file is used as a template to test the different ApplicationPool::Interface implementations.
|
13
|
-
* It is #included in ApplicationPool_PoolTest.cpp and ApplicationPool_Server_PoolTest.cpp
|
14
|
-
*/
|
15
|
-
#ifdef USE_TEMPLATE
|
16
|
-
static void sendTestRequest(SessionPtr &session, const char *uri = "/foo/new") {
|
17
|
-
string headers;
|
18
|
-
#define ADD_HEADER(name, value) \
|
19
|
-
headers.append(name); \
|
20
|
-
headers.append(1, '\0'); \
|
21
|
-
headers.append(value); \
|
22
|
-
headers.append(1, '\0')
|
23
|
-
ADD_HEADER("HTTP_HOST", "www.test.com");
|
24
|
-
ADD_HEADER("QUERY_STRING", "");
|
25
|
-
ADD_HEADER("REQUEST_URI", uri);
|
26
|
-
ADD_HEADER("REQUEST_METHOD", "GET");
|
27
|
-
ADD_HEADER("REMOTE_ADDR", "localhost");
|
28
|
-
ADD_HEADER("SCRIPT_NAME", "");
|
29
|
-
ADD_HEADER("PATH_INFO", uri);
|
30
|
-
ADD_HEADER("PASSENGER_CONNECT_PASSWORD", session->getConnectPassword());
|
31
|
-
session->sendHeaders(headers);
|
32
|
-
}
|
33
|
-
|
34
|
-
static SessionPtr spawnRackApp(ApplicationPool::Ptr pool, const char *appRoot) {
|
35
|
-
PoolOptions options;
|
36
|
-
options.appRoot = appRoot;
|
37
|
-
options.appType = "rack";
|
38
|
-
return pool->get(options);
|
39
|
-
}
|
40
|
-
|
41
|
-
static SessionPtr spawnWsgiApp(ApplicationPool::Ptr pool, const char *appRoot) {
|
42
|
-
PoolOptions options;
|
43
|
-
options.appRoot = appRoot;
|
44
|
-
options.appType = "wsgi";
|
45
|
-
return pool->get(options);
|
46
|
-
}
|
47
|
-
|
48
|
-
namespace {
|
49
|
-
class ReloadLoggingSpawnManager: public SpawnManager {
|
50
|
-
public:
|
51
|
-
vector<string> reloadLog;
|
52
|
-
|
53
|
-
ReloadLoggingSpawnManager(const string &spawnServerCommand,
|
54
|
-
const ServerInstanceDir::GenerationPtr &generation,
|
55
|
-
const AccountsDatabasePtr &accountsDatabase = AccountsDatabasePtr(),
|
56
|
-
const string &rubyCommand = "ruby")
|
57
|
-
: SpawnManager(spawnServerCommand, generation, accountsDatabase, rubyCommand)
|
58
|
-
{ }
|
59
|
-
|
60
|
-
virtual void reload(const string &appRoot) {
|
61
|
-
reloadLog.push_back(appRoot);
|
62
|
-
SpawnManager::reload(appRoot);
|
63
|
-
}
|
64
|
-
};
|
65
|
-
|
66
|
-
struct SpawnRackAppFunction {
|
67
|
-
ApplicationPool::Ptr pool;
|
68
|
-
bool *done;
|
69
|
-
SessionPtr *session;
|
70
|
-
|
71
|
-
SpawnRackAppFunction() {
|
72
|
-
done = NULL;
|
73
|
-
session = NULL;
|
74
|
-
}
|
75
|
-
|
76
|
-
void operator()() {
|
77
|
-
PoolOptions options;
|
78
|
-
options.appRoot = "stub/rack";
|
79
|
-
options.appType = "rack";
|
80
|
-
options.useGlobalQueue = true;
|
81
|
-
SessionPtr session = pool->get(options);
|
82
|
-
*done = true;
|
83
|
-
if (this->session != NULL) {
|
84
|
-
*this->session = session;
|
85
|
-
}
|
86
|
-
}
|
87
|
-
};
|
88
|
-
}
|
89
|
-
|
90
|
-
TEST_METHOD(1) {
|
91
|
-
// Calling ApplicationPool.get() once should return a valid Session.
|
92
|
-
SessionPtr session(spawnRackApp(pool, "stub/rack"));
|
93
|
-
sendTestRequest(session);
|
94
|
-
session->shutdownWriter();
|
95
|
-
|
96
|
-
int reader = session->getStream();
|
97
|
-
string result(readAll(reader));
|
98
|
-
session->closeStream();
|
99
|
-
ensure(result.find("hello <b>world</b>") != string::npos);
|
100
|
-
}
|
101
|
-
|
102
|
-
TEST_METHOD(2) {
|
103
|
-
// Verify that the pool spawns a new app, and that
|
104
|
-
// after the session is closed, the app is kept around.
|
105
|
-
SessionPtr session(spawnRackApp(pool, "stub/rack"));
|
106
|
-
ensure_equals("Before the session was closed, the app was busy", pool->getActive(), 1u);
|
107
|
-
ensure_equals("Before the session was closed, the app was in the pool", pool->getCount(), 1u);
|
108
|
-
session.reset();
|
109
|
-
ensure_equals("After the session is closed, the app is no longer busy", pool->getActive(), 0u);
|
110
|
-
ensure_equals("After the session is closed, the app is kept around", pool->getCount(), 1u);
|
111
|
-
}
|
112
|
-
|
113
|
-
TEST_METHOD(3) {
|
114
|
-
// If we call get() with an application root, then we close the session,
|
115
|
-
// and then we call get() again with the same app group name,
|
116
|
-
// then the pool should not have spawned more than 1 app in total.
|
117
|
-
SessionPtr session(spawnRackApp(pool, "stub/rack"));
|
118
|
-
session.reset();
|
119
|
-
session = spawnRackApp(pool, "stub/rack");
|
120
|
-
ensure_equals(pool->getCount(), 1u);
|
121
|
-
}
|
122
|
-
|
123
|
-
TEST_METHOD(4) {
|
124
|
-
// If we call get() with an app group name, then we call get() again before closing
|
125
|
-
// the session, then the pool will eventually have spawned 2 apps in total.
|
126
|
-
SessionPtr session(spawnRackApp(pool, "stub/rack"));
|
127
|
-
SessionPtr session2(spawnRackApp(pool2, "stub/rack"));
|
128
|
-
EVENTUALLY(5,
|
129
|
-
result = pool->getCount() == 2u;
|
130
|
-
);
|
131
|
-
}
|
132
|
-
|
133
|
-
TEST_METHOD(5) {
|
134
|
-
// If we call get() twice with different app group names,
|
135
|
-
// then the pool should spawn two different apps.
|
136
|
-
TempDirCopy c1("stub/rack", "rackapp1.tmp");
|
137
|
-
TempDirCopy c2("stub/rack", "rackapp2.tmp");
|
138
|
-
replaceStringInFile("rackapp2.tmp/config.ru", "world", "world 2");
|
139
|
-
SessionPtr session = spawnRackApp(pool, "rackapp1.tmp");
|
140
|
-
SessionPtr session2 = spawnRackApp(pool2, "rackapp2.tmp");
|
141
|
-
ensure_equals("Before the sessions were closed, both apps were busy", pool->getActive(), 2u);
|
142
|
-
ensure_equals("Before the sessions were closed, both apps were in the pool", pool->getCount(), 2u);
|
143
|
-
|
144
|
-
sendTestRequest(session);
|
145
|
-
string result = readAll(session->getStream());
|
146
|
-
ensure("Session 1 belongs to the correct app", result.find("hello <b>world</b>") != string::npos);
|
147
|
-
session.reset();
|
148
|
-
|
149
|
-
sendTestRequest(session2);
|
150
|
-
result = readAll(session2->getStream());
|
151
|
-
ensure("Session 2 belongs to the correct app", result.find("hello <b>world 2</b>") != string::npos);
|
152
|
-
session2.reset();
|
153
|
-
}
|
154
|
-
|
155
|
-
TEST_METHOD(6) {
|
156
|
-
// If we call get() twice with different app group names,
|
157
|
-
// and we close both sessions, then both 2 apps should still
|
158
|
-
// be in the pool.
|
159
|
-
TempDirCopy c1("stub/rack", "rackapp1.tmp");
|
160
|
-
TempDirCopy c2("stub/rack", "rackapp2.tmp");
|
161
|
-
SessionPtr session(spawnRackApp(pool, "rackapp1.tmp"));
|
162
|
-
SessionPtr session2(spawnRackApp(pool, "rackapp2.tmp"));
|
163
|
-
session.reset();
|
164
|
-
session2.reset();
|
165
|
-
ensure_equals("There are 0 active apps", pool->getActive(), 0u);
|
166
|
-
ensure_equals("There are 2 apps in total", pool->getCount(), 2u);
|
167
|
-
}
|
168
|
-
|
169
|
-
TEST_METHOD(7) {
|
170
|
-
// If we call get() even though the pool is already full
|
171
|
-
// (active == max), and the app group name is already
|
172
|
-
// in the pool, then the pool must wait until there's an
|
173
|
-
// inactive application.
|
174
|
-
pool->setMax(1);
|
175
|
-
// TODO: How do we test this?
|
176
|
-
}
|
177
|
-
|
178
|
-
TEST_METHOD(8) {
|
179
|
-
// If ApplicationPool spawns a new instance,
|
180
|
-
// and we kill it, then the next get() with the
|
181
|
-
// same application root should not throw an exception:
|
182
|
-
// ApplicationPool should spawn a new instance
|
183
|
-
// after detecting that the original one died.
|
184
|
-
SessionPtr session = spawnRackApp(pool, "stub/rack");
|
185
|
-
kill(session->getPid(), SIGKILL);
|
186
|
-
session.reset();
|
187
|
-
usleep(20000); // Give the process some time to exit.
|
188
|
-
spawnRackApp(pool, "stub/rack"); // should not throw
|
189
|
-
}
|
190
|
-
|
191
|
-
struct PoolWaitTestThread {
|
192
|
-
ApplicationPool::Ptr pool;
|
193
|
-
SessionPtr &m_session;
|
194
|
-
bool &m_done;
|
195
|
-
|
196
|
-
PoolWaitTestThread(const ApplicationPool::Ptr &pool,
|
197
|
-
SessionPtr &session,
|
198
|
-
bool &done)
|
199
|
-
: m_session(session), m_done(done) {
|
200
|
-
this->pool = pool;
|
201
|
-
done = false;
|
202
|
-
}
|
203
|
-
|
204
|
-
void operator()() {
|
205
|
-
m_session = spawnWsgiApp(pool, "stub/wsgi");
|
206
|
-
m_done = true;
|
207
|
-
}
|
208
|
-
};
|
209
|
-
|
210
|
-
TEST_METHOD(9) {
|
211
|
-
// If we call get() even though the pool is already full
|
212
|
-
// (active == max), and the app group name is *not* already
|
213
|
-
// in the pool, then the pool will wait until enough sessions
|
214
|
-
// have been closed.
|
215
|
-
|
216
|
-
// Make the pool full.
|
217
|
-
pool->setMax(2);
|
218
|
-
SessionPtr session1 = spawnRackApp(pool, "stub/rack");
|
219
|
-
SessionPtr session2 = spawnRackApp(pool2, "stub/rack");
|
220
|
-
EVENTUALLY(5,
|
221
|
-
result = pool->getCount() == 2u;
|
222
|
-
);
|
223
|
-
session1.reset();
|
224
|
-
session2.reset();
|
225
|
-
EVENTUALLY(5,
|
226
|
-
result = pool->getActive() == 0u;
|
227
|
-
);
|
228
|
-
session1 = spawnRackApp(pool, "stub/rack");
|
229
|
-
session2 = spawnRackApp(pool2, "stub/rack");
|
230
|
-
ensure_equals(pool->getActive(), 2u);
|
231
|
-
|
232
|
-
// Now spawn an app with a different app root.
|
233
|
-
SessionPtr session3;
|
234
|
-
bool done;
|
235
|
-
TempThread thr(PoolWaitTestThread(pool2, session3, done));
|
236
|
-
usleep(500000);
|
237
|
-
ensure("ApplicationPool is still waiting", !done);
|
238
|
-
ensure_equals(pool->getActive(), 2u);
|
239
|
-
ensure_equals(pool->getCount(), 2u);
|
240
|
-
|
241
|
-
// Now release one slot from the pool.
|
242
|
-
session1.reset();
|
243
|
-
|
244
|
-
// Session 3 should eventually be opened.
|
245
|
-
EVENTUALLY(10,
|
246
|
-
result = done;
|
247
|
-
);
|
248
|
-
ensure_equals(pool->getActive(), 2u);
|
249
|
-
ensure_equals(pool->getCount(), 2u);
|
250
|
-
}
|
251
|
-
|
252
|
-
TEST_METHOD(10) {
|
253
|
-
// If we call get(), and:
|
254
|
-
// * the pool is already full, but there are inactive apps
|
255
|
-
// (active < count && count == max)
|
256
|
-
// and
|
257
|
-
// * the app group name for this get() is *not* already in the pool
|
258
|
-
// then the an inactive app should be killed in order to
|
259
|
-
// satisfy this get() command.
|
260
|
-
TempDirCopy c1("stub/rack", "rackapp1.tmp");
|
261
|
-
TempDirCopy c2("stub/rack", "rackapp2.tmp");
|
262
|
-
|
263
|
-
// Make the pool full.
|
264
|
-
pool->setMax(2);
|
265
|
-
SessionPtr session1 = spawnRackApp(pool, "rackapp1.tmp");
|
266
|
-
SessionPtr session2 = spawnRackApp(pool2, "rackapp1.tmp");
|
267
|
-
EVENTUALLY(5,
|
268
|
-
result = pool->getCount() == 2u;
|
269
|
-
);
|
270
|
-
session1.reset();
|
271
|
-
session2.reset();
|
272
|
-
EVENTUALLY(5,
|
273
|
-
result = pool->getActive() == 0u;
|
274
|
-
);
|
275
|
-
|
276
|
-
// Now spawn a different app.
|
277
|
-
session1 = spawnRackApp(pool, "rackapp2.tmp");
|
278
|
-
ensure_equals(pool->getActive(), 1u);
|
279
|
-
ensure_equals(pool->getCount(), 2u);
|
280
|
-
}
|
281
|
-
|
282
|
-
TEST_METHOD(11) {
|
283
|
-
// A Session should still be usable after the pool has been destroyed.
|
284
|
-
SessionPtr session = spawnRackApp(pool, "stub/rack");
|
285
|
-
pool->clear();
|
286
|
-
pool.reset();
|
287
|
-
pool2.reset();
|
288
|
-
|
289
|
-
sendTestRequest(session);
|
290
|
-
session->shutdownWriter();
|
291
|
-
|
292
|
-
int reader = session->getStream();
|
293
|
-
string result = readAll(reader);
|
294
|
-
session->closeStream();
|
295
|
-
ensure(result.find("hello <b>world</b>") != string::npos);
|
296
|
-
}
|
297
|
-
|
298
|
-
TEST_METHOD(12) {
|
299
|
-
// If tmp/restart.txt didn't exist but has now been created,
|
300
|
-
// then the applications under app_root should be restarted.
|
301
|
-
struct stat buf;
|
302
|
-
TempDirCopy c("stub/rack", "rackapp.tmp");
|
303
|
-
SessionPtr session1 = spawnRackApp(pool, "rackapp.tmp");
|
304
|
-
SessionPtr session2 = spawnRackApp(pool2, "rackapp.tmp");
|
305
|
-
session1.reset();
|
306
|
-
session2.reset();
|
307
|
-
EVENTUALLY(5,
|
308
|
-
result = pool->getCount() == 2u;
|
309
|
-
);
|
310
|
-
|
311
|
-
touchFile("rackapp.tmp/tmp/restart.txt");
|
312
|
-
spawnRackApp(pool, "rackapp.tmp");
|
313
|
-
|
314
|
-
ensure_equals("No apps are active", pool->getActive(), 0u);
|
315
|
-
ensure_equals("Both apps are killed, and a new one was spawned",
|
316
|
-
pool->getCount(), 1u);
|
317
|
-
ensure("Restart file still exists",
|
318
|
-
stat("rackapp.tmp/tmp/restart.txt", &buf) == 0);
|
319
|
-
}
|
320
|
-
|
321
|
-
TEST_METHOD(13) {
|
322
|
-
// If tmp/restart.txt was present, and its timestamp changed
|
323
|
-
// since the last check, then the applications under the app group name
|
324
|
-
// should still be restarted. However, a subsequent get()
|
325
|
-
// should not result in a restart.
|
326
|
-
pid_t old_pid;
|
327
|
-
TempDirCopy c("stub/rack", "rackapp.tmp");
|
328
|
-
TempDir d("rackapp.tmp/tmp/restart.txt");
|
329
|
-
SessionPtr session = spawnRackApp(pool, "rackapp.tmp");
|
330
|
-
old_pid = session->getPid();
|
331
|
-
session.reset();
|
332
|
-
EVENTUALLY(5,
|
333
|
-
result = pool->getActive() == 0u;
|
334
|
-
);
|
335
|
-
|
336
|
-
touchFile("rackapp.tmp/tmp/restart.txt", 10);
|
337
|
-
|
338
|
-
session = spawnRackApp(pool, "rackapp.tmp");
|
339
|
-
ensure("The app was restarted", session->getPid() != old_pid);
|
340
|
-
old_pid = session->getPid();
|
341
|
-
session.reset();
|
342
|
-
EVENTUALLY(5,
|
343
|
-
result = pool->getActive() == 0u;
|
344
|
-
);
|
345
|
-
|
346
|
-
session = spawnRackApp(pool, "rackapp.tmp");
|
347
|
-
ensure_equals("The app was not restarted",
|
348
|
-
old_pid, session->getPid());
|
349
|
-
}
|
350
|
-
|
351
|
-
TEST_METHOD(15) {
|
352
|
-
// Test whether restarting with restart.txt really results in code reload.
|
353
|
-
TempDirCopy c("stub/rack", "rackapp.tmp");
|
354
|
-
SessionPtr session = spawnRackApp(pool, "rackapp.tmp");
|
355
|
-
sendTestRequest(session);
|
356
|
-
string result = readAll(session->getStream());
|
357
|
-
ensure(result.find("hello <b>world</b>") != string::npos);
|
358
|
-
session.reset();
|
359
|
-
EVENTUALLY(5,
|
360
|
-
result = pool->getActive() == 0u;
|
361
|
-
);
|
362
|
-
|
363
|
-
touchFile("rackapp.tmp/tmp/restart.txt");
|
364
|
-
replaceStringInFile("rackapp.tmp/config.ru", "world", "world 2");
|
365
|
-
|
366
|
-
session = spawnRackApp(pool, "rackapp.tmp");
|
367
|
-
sendTestRequest(session);
|
368
|
-
result = readAll(session->getStream());
|
369
|
-
ensure("App code has been reloaded", result.find("hello <b>world 2</b>") != string::npos);
|
370
|
-
}
|
371
|
-
|
372
|
-
TEST_METHOD(16) {
|
373
|
-
// If tmp/always_restart.txt is present and is a file,
|
374
|
-
// then the application under app_root should be always restarted.
|
375
|
-
struct stat buf;
|
376
|
-
pid_t old_pid;
|
377
|
-
TempDirCopy c("stub/rack", "rackapp.tmp");
|
378
|
-
SessionPtr session1 = spawnRackApp(pool, "rackapp.tmp");
|
379
|
-
SessionPtr session2 = spawnRackApp(pool2, "rackapp.tmp");
|
380
|
-
session1.reset();
|
381
|
-
session2.reset();
|
382
|
-
EVENTUALLY(5,
|
383
|
-
result = pool->getActive() == 0u && pool->getCount() == 2u;
|
384
|
-
);
|
385
|
-
|
386
|
-
touchFile("rackapp.tmp/tmp/always_restart.txt");
|
387
|
-
|
388
|
-
// This get() results in a restart.
|
389
|
-
session1 = spawnRackApp(pool, "rackapp.tmp");
|
390
|
-
old_pid = session1->getPid();
|
391
|
-
session1.reset();
|
392
|
-
EVENTUALLY(5,
|
393
|
-
// First restart: no apps are active
|
394
|
-
result = pool->getActive() == 0u;
|
395
|
-
);
|
396
|
-
ensure_equals("First restart: the first 2 apps were killed, and a new one was spawned",
|
397
|
-
pool->getCount(), 1u);
|
398
|
-
ensure("always_restart file has not been deleted",
|
399
|
-
stat("rackapp.tmp/tmp/always_restart.txt", &buf) == 0);
|
400
|
-
|
401
|
-
// This get() results in a restart as well.
|
402
|
-
session1 = spawnRackApp(pool, "rackapp.tmp");
|
403
|
-
ensure(old_pid != session1->getPid());
|
404
|
-
session1.reset();
|
405
|
-
EVENTUALLY(5,
|
406
|
-
// Second restart: no apps are active
|
407
|
-
result = pool->getActive() == 0u;
|
408
|
-
);
|
409
|
-
ensure_equals("Second restart: the last app was killed, and a new one was spawned",
|
410
|
-
pool->getCount(), 1u);
|
411
|
-
ensure("always_restart file has not been deleted",
|
412
|
-
stat("rackapp.tmp/tmp/always_restart.txt", &buf) == 0);
|
413
|
-
}
|
414
|
-
|
415
|
-
TEST_METHOD(17) {
|
416
|
-
// If tmp/always_restart.txt is present and is a directory,
|
417
|
-
// then the application under app_root should be always restarted.
|
418
|
-
struct stat buf;
|
419
|
-
pid_t old_pid;
|
420
|
-
TempDirCopy c("stub/rack", "rackapp.tmp");
|
421
|
-
SessionPtr session1 = spawnRackApp(pool, "rackapp.tmp");
|
422
|
-
SessionPtr session2 = spawnRackApp(pool2, "rackapp.tmp");
|
423
|
-
session1.reset();
|
424
|
-
session2.reset();
|
425
|
-
EVENTUALLY(5,
|
426
|
-
result = pool->getActive() == 0u && pool->getCount() == 2u;
|
427
|
-
);
|
428
|
-
|
429
|
-
TempDir d("rackapp.tmp/tmp/always_restart.txt");
|
430
|
-
|
431
|
-
// This get() results in a restart.
|
432
|
-
session1 = spawnRackApp(pool, "rackapp.tmp");
|
433
|
-
old_pid = session1->getPid();
|
434
|
-
session1.reset();
|
435
|
-
EVENTUALLY(5,
|
436
|
-
// First restart: no apps are active
|
437
|
-
result = pool->getActive() == 0u;
|
438
|
-
);
|
439
|
-
ensure_equals("First restart: the first 2 apps were killed, and a new one was spawned",
|
440
|
-
pool->getCount(), 1u);
|
441
|
-
ensure("always_restart directory has not been deleted",
|
442
|
-
stat("rackapp.tmp/tmp/always_restart.txt", &buf) == 0);
|
443
|
-
|
444
|
-
// This get() results in a restart as well.
|
445
|
-
session1 = spawnRackApp(pool, "rackapp.tmp");
|
446
|
-
ensure(old_pid != session1->getPid());
|
447
|
-
session1.reset();
|
448
|
-
EVENTUALLY(5,
|
449
|
-
// Second restart: no apps are active
|
450
|
-
result = pool->getActive() == 0u;
|
451
|
-
);
|
452
|
-
ensure_equals("Second restart: the last app was killed, and a new one was spawned",
|
453
|
-
pool->getCount(), 1u);
|
454
|
-
ensure("always_restart directory has not been deleted",
|
455
|
-
stat("rackapp.tmp/tmp/always_restart.txt", &buf) == 0);
|
456
|
-
}
|
457
|
-
|
458
|
-
TEST_METHOD(18) {
|
459
|
-
// Test whether restarting with tmp/always_restart.txt really results in code reload.
|
460
|
-
TempDirCopy c("stub/rack", "rackapp.tmp");
|
461
|
-
SessionPtr session = spawnRackApp(pool, "rackapp.tmp");
|
462
|
-
sendTestRequest(session);
|
463
|
-
string result = readAll(session->getStream());
|
464
|
-
ensure(result.find("hello <b>world</b>") != string::npos);
|
465
|
-
session.reset();
|
466
|
-
|
467
|
-
touchFile("rackapp.tmp/tmp/always_restart.txt");
|
468
|
-
replaceStringInFile("rackapp.tmp/config.ru", "world", "world 2");
|
469
|
-
|
470
|
-
session = spawnRackApp(pool, "rackapp.tmp");
|
471
|
-
sendTestRequest(session);
|
472
|
-
result = readAll(session->getStream());
|
473
|
-
ensure("App code has been reloaded (1)", result.find("hello <b>world 2</b>") != string::npos);
|
474
|
-
session.reset();
|
475
|
-
EVENTUALLY(5,
|
476
|
-
result = pool->getActive() == 0u;
|
477
|
-
);
|
478
|
-
|
479
|
-
replaceStringInFile("rackapp.tmp/config.ru", "world 2", "world 3");
|
480
|
-
session = spawnRackApp(pool, "rackapp.tmp");
|
481
|
-
sendTestRequest(session);
|
482
|
-
result = readAll(session->getStream());
|
483
|
-
ensure("App code has been reloaded (2)", result.find("hello <b>world 3</b>") != string::npos);
|
484
|
-
session.reset();
|
485
|
-
}
|
486
|
-
|
487
|
-
TEST_METHOD(19) {
|
488
|
-
// If tmp/restart.txt and tmp/always_restart.txt are present,
|
489
|
-
// the application under app_root should still be restarted and
|
490
|
-
// both files must be kept.
|
491
|
-
pid_t old_pid, pid;
|
492
|
-
struct stat buf;
|
493
|
-
TempDirCopy c("stub/rack", "rackapp.tmp");
|
494
|
-
SessionPtr session1 = spawnRackApp(pool, "rackapp.tmp");
|
495
|
-
SessionPtr session2 = spawnRackApp(pool2, "rackapp.tmp");
|
496
|
-
session1.reset();
|
497
|
-
session2.reset();
|
498
|
-
EVENTUALLY(5,
|
499
|
-
result = pool->getActive() == 0u && pool->getCount() == 2u;
|
500
|
-
);
|
501
|
-
|
502
|
-
touchFile("rackapp.tmp/tmp/restart.txt");
|
503
|
-
touchFile("rackapp.tmp/tmp/always_restart.txt");
|
504
|
-
|
505
|
-
old_pid = spawnRackApp(pool, "rackapp.tmp")->getPid();
|
506
|
-
ensure("always_restart.txt file has not been deleted",
|
507
|
-
stat("rackapp.tmp/tmp/always_restart.txt", &buf) == 0);
|
508
|
-
ensure("restart.txt file has not been deleted",
|
509
|
-
stat("rackapp.tmp/tmp/restart.txt", &buf) == 0);
|
510
|
-
EVENTUALLY(5,
|
511
|
-
result = pool->getActive() == 0u;
|
512
|
-
);
|
513
|
-
|
514
|
-
pid = spawnRackApp(pool, "rackapp.tmp")->getPid();
|
515
|
-
ensure("The app was restarted", pid != old_pid);
|
516
|
-
}
|
517
|
-
|
518
|
-
TEST_METHOD(20) {
|
519
|
-
// It should look for restart.txt in the directory given by
|
520
|
-
// the restartDir option, if available.
|
521
|
-
struct stat buf;
|
522
|
-
char path[1024];
|
523
|
-
PoolOptions options("stub/rack");
|
524
|
-
options.appType = "rack";
|
525
|
-
options.restartDir = string(getcwd(path, sizeof(path))) + "/stub/rack";
|
526
|
-
|
527
|
-
SessionPtr session1 = pool->get(options);
|
528
|
-
SessionPtr session2 = pool2->get(options);
|
529
|
-
session1.reset();
|
530
|
-
session2.reset();
|
531
|
-
EVENTUALLY(5,
|
532
|
-
result = pool->getActive() == 0u && pool->getCount() == 2u;
|
533
|
-
);
|
534
|
-
|
535
|
-
DeleteFileEventually f("stub/rack/restart.txt");
|
536
|
-
touchFile("stub/rack/restart.txt");
|
537
|
-
|
538
|
-
pool->get(options);
|
539
|
-
|
540
|
-
ensure_equals("No apps are active", pool->getActive(), 0u);
|
541
|
-
ensure_equals("Both apps are killed, and a new one was spawned",
|
542
|
-
pool->getCount(), 1u);
|
543
|
-
ensure("Restart file still exists",
|
544
|
-
stat("stub/rack/restart.txt", &buf) == 0);
|
545
|
-
}
|
546
|
-
|
547
|
-
TEST_METHOD(21) {
|
548
|
-
// restartDir may also be a directory relative to the
|
549
|
-
// application root.
|
550
|
-
struct stat buf;
|
551
|
-
PoolOptions options("stub/rack");
|
552
|
-
options.appType = "rack";
|
553
|
-
options.restartDir = "public";
|
554
|
-
|
555
|
-
SessionPtr session1 = pool->get(options);
|
556
|
-
SessionPtr session2 = pool2->get(options);
|
557
|
-
session1.reset();
|
558
|
-
session2.reset();
|
559
|
-
EVENTUALLY(5,
|
560
|
-
result = pool->getActive() == 0u && pool->getCount() == 2u;
|
561
|
-
);
|
562
|
-
|
563
|
-
DeleteFileEventually f("stub/rack/public/restart.txt");
|
564
|
-
touchFile("stub/rack/public/restart.txt");
|
565
|
-
|
566
|
-
pool->get(options);
|
567
|
-
|
568
|
-
ensure_equals("No apps are active", pool->getActive(), 0u);
|
569
|
-
ensure_equals("Both apps are killed, and a new one was spawned",
|
570
|
-
pool->getCount(), 1u);
|
571
|
-
ensure("Restart file still exists",
|
572
|
-
stat("stub/rack/public/restart.txt", &buf) == 0);
|
573
|
-
}
|
574
|
-
|
575
|
-
TEST_METHOD(22) {
|
576
|
-
// The cleaner thread should clean idle applications.
|
577
|
-
pool->setMaxIdleTime(1);
|
578
|
-
spawnRackApp(pool, "stub/rack");
|
579
|
-
EVENTUALLY(10,
|
580
|
-
result = pool->getCount() == 0u;
|
581
|
-
);
|
582
|
-
|
583
|
-
time_t begin = time(NULL);
|
584
|
-
while (pool->getCount() == 1u && time(NULL) - begin < 10) {
|
585
|
-
usleep(100000);
|
586
|
-
}
|
587
|
-
ensure_equals("App should have been cleaned up", pool->getCount(), 0u);
|
588
|
-
}
|
589
|
-
|
590
|
-
TEST_METHOD(23) {
|
591
|
-
// MaxPerApp is respected.
|
592
|
-
pool->setMax(3);
|
593
|
-
pool->setMaxPerApp(1);
|
594
|
-
|
595
|
-
// We connect to stub/rack while it already has an instance with
|
596
|
-
// 1 request in its queue. Assert that the pool doesn't spawn
|
597
|
-
// another instance.
|
598
|
-
SessionPtr session1 = spawnRackApp(pool, "stub/rack");
|
599
|
-
SessionPtr session2 = spawnRackApp(pool2, "stub/rack");
|
600
|
-
|
601
|
-
// We connect to stub/wsgi. Assert that the pool spawns a new
|
602
|
-
// instance for this app.
|
603
|
-
TempDirCopy c("stub/wsgi", "wsgiapp.tmp");
|
604
|
-
ApplicationPool::Ptr pool3 = newPoolConnection();
|
605
|
-
SessionPtr session3 = spawnWsgiApp(pool3, "wsgiapp.tmp");
|
606
|
-
ensure_equals(pool->getCount(), 2u);
|
607
|
-
}
|
608
|
-
|
609
|
-
TEST_METHOD(24) {
|
610
|
-
// Application instance is shutdown after 'maxRequests' requests.
|
611
|
-
PoolOptions options("stub/rack");
|
612
|
-
int reader;
|
613
|
-
pid_t originalPid;
|
614
|
-
SessionPtr session;
|
615
|
-
|
616
|
-
options.appType = "rack";
|
617
|
-
options.maxRequests = 4;
|
618
|
-
pool->setMax(1);
|
619
|
-
session = pool->get(options);
|
620
|
-
originalPid = session->getPid();
|
621
|
-
session.reset();
|
622
|
-
EVENTUALLY(5,
|
623
|
-
result = pool->getActive() == 0u;
|
624
|
-
);
|
625
|
-
|
626
|
-
for (unsigned int i = 0; i < 4; i++) {
|
627
|
-
session = pool->get(options);
|
628
|
-
sendTestRequest(session);
|
629
|
-
session->shutdownWriter();
|
630
|
-
reader = session->getStream();
|
631
|
-
readAll(reader);
|
632
|
-
// Must explicitly call reset() here because we
|
633
|
-
// want to close the session right now.
|
634
|
-
session.reset();
|
635
|
-
EVENTUALLY(5,
|
636
|
-
result = pool->getActive() == 0u;
|
637
|
-
);
|
638
|
-
}
|
639
|
-
|
640
|
-
session = pool->get(options);
|
641
|
-
ensure(session->getPid() != originalPid);
|
642
|
-
}
|
643
|
-
|
644
|
-
TEST_METHOD(25) {
|
645
|
-
// If global queueing mode is enabled, then get() waits until
|
646
|
-
// there's at least one idle backend process for this application
|
647
|
-
// domain.
|
648
|
-
pool->setMax(1);
|
649
|
-
|
650
|
-
PoolOptions options;
|
651
|
-
options.appRoot = "stub/rack";
|
652
|
-
options.appType = "rack";
|
653
|
-
options.useGlobalQueue = true;
|
654
|
-
SessionPtr session = pool->get(options);
|
655
|
-
|
656
|
-
bool done = false;
|
657
|
-
SpawnRackAppFunction func;
|
658
|
-
func.pool = pool2;
|
659
|
-
func.done = &done;
|
660
|
-
TempThread thr(func);
|
661
|
-
|
662
|
-
// Previous session hasn't been closed yet, so pool should still
|
663
|
-
// be waiting.
|
664
|
-
usleep(100000);
|
665
|
-
ensure("(1)", !done);
|
666
|
-
ensure_equals("(2)", pool->getGlobalQueueSize(), 1u);
|
667
|
-
ensure_equals("(3)", pool->getActive(), 1u);
|
668
|
-
ensure_equals("(4)", pool->getCount(), 1u);
|
669
|
-
|
670
|
-
// Close the previous session. The thread should now finish.
|
671
|
-
session.reset();
|
672
|
-
EVENTUALLY(5,
|
673
|
-
result = done;
|
674
|
-
);
|
675
|
-
}
|
676
|
-
|
677
|
-
TEST_METHOD(26) {
|
678
|
-
// When a previous application group spinned down, and we touched
|
679
|
-
// restart.txt and try to spin up a new process for this domain,
|
680
|
-
// then any ApplicationSpawner/FrameworkSpawner processes should be
|
681
|
-
// killed first.
|
682
|
-
SessionPtr session;
|
683
|
-
TempDirCopy c1("stub/rack", "rackapp1.tmp");
|
684
|
-
TempDirCopy c2("stub/rack", "rackapp2.tmp");
|
685
|
-
shared_ptr<ReloadLoggingSpawnManager> spawnManager(
|
686
|
-
new ReloadLoggingSpawnManager("../helper-scripts/passenger-spawn-server", generation)
|
687
|
-
);
|
688
|
-
reinitializeWithSpawnManager(spawnManager);
|
689
|
-
|
690
|
-
pool->setMax(1);
|
691
|
-
session = spawnRackApp(pool, "rackapp1.tmp");
|
692
|
-
session.reset();
|
693
|
-
session = spawnRackApp(pool, "rackapp2.tmp");
|
694
|
-
ensure_equals("rackapp2.tmp is not reloaded because restart.txt is not touched",
|
695
|
-
spawnManager->reloadLog.size(), 0u);
|
696
|
-
session.reset();
|
697
|
-
EVENTUALLY(5,
|
698
|
-
result = pool->getActive() == 0u;
|
699
|
-
);
|
700
|
-
|
701
|
-
touchFile("rackapp1.tmp/tmp/restart.txt");
|
702
|
-
session = spawnRackApp(pool, "rackapp1.tmp");
|
703
|
-
ensure_equals("rackapp1.tmp is reloaded because restart.txt is touched (1)",
|
704
|
-
spawnManager->reloadLog.size(), 1u);
|
705
|
-
ensure_equals("rackapp1.tmp is reloaded because restart.txt is touched (2)",
|
706
|
-
spawnManager->reloadLog[0], "rackapp1.tmp");
|
707
|
-
}
|
708
|
-
|
709
|
-
TEST_METHOD(27) {
|
710
|
-
// Test inspect()
|
711
|
-
SessionPtr session1 = spawnRackApp(pool, "stub/rack");
|
712
|
-
string str = pool->inspect();
|
713
|
-
ensure("Contains 'max = '", str.find("max ") != string::npos);
|
714
|
-
ensure("Contains PID", str.find("PID: " + toString(session1->getPid())) != string::npos);
|
715
|
-
}
|
716
|
-
|
717
|
-
TEST_METHOD(28) {
|
718
|
-
// Test toXml(true)
|
719
|
-
SessionPtr session1 = spawnRackApp(pool, "stub/rack");
|
720
|
-
string xml = pool->toXml();
|
721
|
-
ensure("Contains <process>", xml.find("<process>") != string::npos);
|
722
|
-
ensure("Contains PID", xml.find("<pid>" + toString(session1->getPid()) + "</pid>") != string::npos);
|
723
|
-
ensure("Contains sensitive information", xml.find("<server_sockets>") != string::npos);
|
724
|
-
}
|
725
|
-
|
726
|
-
TEST_METHOD(29) {
|
727
|
-
// Test toXml(false)
|
728
|
-
SessionPtr session1 = spawnRackApp(pool, "stub/rack");
|
729
|
-
string xml = pool->toXml(false);
|
730
|
-
ensure("Contains <process>", xml.find("<process>") != string::npos);
|
731
|
-
ensure("Contains PID", xml.find("<pid>" + toString(session1->getPid()) + "</pid>") != string::npos);
|
732
|
-
ensure("Does not contain sensitive information", xml.find("<server_sockets>") == string::npos);
|
733
|
-
}
|
734
|
-
|
735
|
-
TEST_METHOD(30) {
|
736
|
-
// Test detach().
|
737
|
-
|
738
|
-
// Create 2 processes, where only the first one is active.
|
739
|
-
SessionPtr session1 = spawnRackApp(pool, "stub/rack");
|
740
|
-
SessionPtr session2 = spawnRackApp(pool2, "stub/rack");
|
741
|
-
session2.reset();
|
742
|
-
EVENTUALLY(5,
|
743
|
-
result = pool->getActive() == 1u && pool->getCount() == 2u;
|
744
|
-
);
|
745
|
-
|
746
|
-
// Make sure session2 refers to a different process than session1.
|
747
|
-
session2 = spawnRackApp(pool2, "stub/rack");
|
748
|
-
string session2dk = session2->getDetachKey();
|
749
|
-
session2.reset();
|
750
|
-
EVENTUALLY(5,
|
751
|
-
result = pool->getActive() == 1u;
|
752
|
-
);
|
753
|
-
|
754
|
-
// First detach works. It was active so the 'active' property
|
755
|
-
// is decremented.
|
756
|
-
ensure("(10)", pool->detach(session1->getDetachKey()));
|
757
|
-
ensure_equals("(11)", pool->getActive(), 0u);
|
758
|
-
ensure_equals("(12)", pool->getCount(), 1u);
|
759
|
-
|
760
|
-
// Second detach with the same identifier doesn't do anything.
|
761
|
-
ensure("(20)", !pool->detach(session1->getDetachKey()));
|
762
|
-
ensure_equals("(21)", pool->getActive(), 0u);
|
763
|
-
ensure_equals("(22)", pool->getCount(), 1u);
|
764
|
-
|
765
|
-
// Detaching an inactive process works too.
|
766
|
-
ensure("(30)", pool->detach(session2dk));
|
767
|
-
ensure_equals("(31)", pool->getActive(), 0u);
|
768
|
-
ensure_equals("(32)", pool->getCount(), 0u);
|
769
|
-
}
|
770
|
-
|
771
|
-
TEST_METHOD(31) {
|
772
|
-
// If the app group does not yet exist, and options.minProcesses > 0,
|
773
|
-
// then get() will spawn 1 process immediately, return its session,
|
774
|
-
// and spawn more processes in the background until options.minProcesses
|
775
|
-
// is satisfied.
|
776
|
-
TempDirCopy c1("stub/rack", "rackapp.tmp");
|
777
|
-
PoolOptions options;
|
778
|
-
options.appRoot = "rackapp.tmp";
|
779
|
-
options.appType = "rack";
|
780
|
-
options.minProcesses = 3;
|
781
|
-
options.spawnMethod = "conservative";
|
782
|
-
|
783
|
-
writeFile("rackapp.tmp/config.ru",
|
784
|
-
"sleep 0.1\n"
|
785
|
-
"run lambda {}\n");
|
786
|
-
|
787
|
-
SessionPtr session1 = pool->get(options);
|
788
|
-
ensure_equals(pool->getActive(), 1u);
|
789
|
-
ensure_equals(pool->getCount(), 1u);
|
790
|
-
|
791
|
-
EVENTUALLY(5,
|
792
|
-
result = pool->getCount() == 3u;
|
793
|
-
);
|
794
|
-
}
|
795
|
-
|
796
|
-
TEST_METHOD(32) {
|
797
|
-
// If the app group already exists, all processes are active,
|
798
|
-
// count < max, options.minProcesses > 0 and global queuing turned off,
|
799
|
-
// then get() will check out an existing process immediately
|
800
|
-
// and spawn new ones in the background until options.minProcesses
|
801
|
-
// is satisfied.
|
802
|
-
TempDirCopy c1("stub/rack", "rackapp.tmp");
|
803
|
-
PoolOptions options;
|
804
|
-
options.appRoot = "rackapp.tmp";
|
805
|
-
options.appType = "rack";
|
806
|
-
options.spawnMethod = "conservative";
|
807
|
-
options.minProcesses = 3;
|
808
|
-
pool->setMax(3);
|
809
|
-
|
810
|
-
// Spawn a single process.
|
811
|
-
SessionPtr session1 = pool->get(options);
|
812
|
-
ensure_equals(pool->getActive(), 1u);
|
813
|
-
ensure_equals(pool->getCount(), 1u);
|
814
|
-
|
815
|
-
writeFile("rackapp.tmp/config.ru",
|
816
|
-
"sleep 0.1\n"
|
817
|
-
"run lambda {}\n");
|
818
|
-
|
819
|
-
// Now call get(); this one will use the previous process
|
820
|
-
// and spawn a new one in the background.
|
821
|
-
SessionPtr session2 = pool2->get(options);
|
822
|
-
ensure_equals(pool->getActive(), 1u);
|
823
|
-
ensure_equals(pool->getCount(), 1u);
|
824
|
-
ensure_equals(session1->getPid(), session2->getPid());
|
825
|
-
|
826
|
-
EVENTUALLY(5,
|
827
|
-
result = pool->getCount() == 3u;
|
828
|
-
);
|
829
|
-
}
|
830
|
-
|
831
|
-
/* If the app group already exists, all processes are active,
|
832
|
-
* count < max, options.minProcesses > 0 and global queuing turned on,
|
833
|
-
* then get() will wait until either
|
834
|
-
* (1) an existing process becomes inactive.
|
835
|
-
* or until
|
836
|
-
* (2) a new process has been spawned.
|
837
|
-
*/
|
838
|
-
|
839
|
-
TEST_METHOD(33) {
|
840
|
-
// Here we test scenario (1).
|
841
|
-
PoolOptions options;
|
842
|
-
options.appRoot = "stub/rack";
|
843
|
-
options.appType = "rack";
|
844
|
-
options.minProcesses = 3;
|
845
|
-
options.useGlobalQueue = true;
|
846
|
-
pool->setMax(3);
|
847
|
-
|
848
|
-
ApplicationPool::Ptr pool3 = newPoolConnection();
|
849
|
-
ApplicationPool::Ptr pool4 = newPoolConnection();
|
850
|
-
|
851
|
-
// Spawn 3 processes.
|
852
|
-
SessionPtr session1 = pool->get(options);
|
853
|
-
SessionPtr session2 = pool2->get(options);
|
854
|
-
session2.reset();
|
855
|
-
EVENTUALLY(5,
|
856
|
-
result = pool->getCount() == 3u;
|
857
|
-
);
|
858
|
-
|
859
|
-
// Make sure all of them are active.
|
860
|
-
session2 = pool2->get(options);
|
861
|
-
SessionPtr session3 = pool3->get(options);
|
862
|
-
ensure_equals(pool->getActive(), 3u);
|
863
|
-
ensure_equals(pool->getCount(), 3u);
|
864
|
-
|
865
|
-
// Now call get() in a thread.
|
866
|
-
SpawnRackAppFunction func;
|
867
|
-
bool done = false;
|
868
|
-
func.pool = pool4;
|
869
|
-
func.done = &done;
|
870
|
-
TempThread thr(func);
|
871
|
-
|
872
|
-
usleep(20000);
|
873
|
-
ensure("Still waiting on global queue", !done);
|
874
|
-
ensure_equals(pool->getGlobalQueueSize(), 1u);
|
875
|
-
|
876
|
-
// Make 1 process available.
|
877
|
-
session1.reset();
|
878
|
-
EVENTUALLY(5,
|
879
|
-
result = done;
|
880
|
-
);
|
881
|
-
}
|
882
|
-
|
883
|
-
TEST_METHOD(34) {
|
884
|
-
// Here we test scenario (2).
|
885
|
-
PoolOptions options;
|
886
|
-
options.appRoot = "stub/rack";
|
887
|
-
options.appType = "rack";
|
888
|
-
options.minProcesses = 3;
|
889
|
-
options.useGlobalQueue = true;
|
890
|
-
pool->setMax(3);
|
891
|
-
|
892
|
-
ApplicationPool::Ptr pool3 = newPoolConnection();
|
893
|
-
ApplicationPool::Ptr pool4 = newPoolConnection();
|
894
|
-
ApplicationPool::Ptr pool5 = newPoolConnection();
|
895
|
-
|
896
|
-
// Spawn 3 processes.
|
897
|
-
SessionPtr session1 = pool->get(options);
|
898
|
-
SessionPtr session2 = pool2->get(options);
|
899
|
-
session2.reset();
|
900
|
-
EVENTUALLY(5,
|
901
|
-
result = pool->getCount() == 3u;
|
902
|
-
);
|
903
|
-
|
904
|
-
// Make sure all of them are active.
|
905
|
-
session2 = pool2->get(options);
|
906
|
-
SessionPtr session3 = pool3->get(options);
|
907
|
-
ensure_equals(pool->getActive(), 3u);
|
908
|
-
ensure_equals(pool->getCount(), 3u);
|
909
|
-
|
910
|
-
// Now call get() in a thread.
|
911
|
-
SpawnRackAppFunction func1;
|
912
|
-
SessionPtr session4;
|
913
|
-
bool done1 = false;
|
914
|
-
func1.pool = pool4;
|
915
|
-
func1.done = &done1;
|
916
|
-
func1.session = &session4;
|
917
|
-
TempThread thr1(func1);
|
918
|
-
|
919
|
-
// And again.
|
920
|
-
SpawnRackAppFunction func2;
|
921
|
-
SessionPtr session5;
|
922
|
-
bool done2 = false;
|
923
|
-
func2.pool = pool5;
|
924
|
-
func2.done = &done2;
|
925
|
-
func2.session = &session5;
|
926
|
-
TempThread thr2(func2);
|
927
|
-
|
928
|
-
// We should now arrive at a state where there are 3 processes, all
|
929
|
-
// busy, and 2 threads waiting on the global queue.
|
930
|
-
usleep(20000);
|
931
|
-
ensure("Still waiting on global queue", !done1 && !done2);
|
932
|
-
ensure_equals(pool->getGlobalQueueSize(), 2u);
|
933
|
-
|
934
|
-
// Increasing the max will cause one of the threads to wake
|
935
|
-
// up, start a spawn action in the background, and go to sleep
|
936
|
-
// again. Eventually the new process will be done spawning,
|
937
|
-
// causing one of the threads to wake up. The other one will
|
938
|
-
// continue to wait.
|
939
|
-
pool->setMax(4);
|
940
|
-
EVENTUALLY(5,
|
941
|
-
result = (done1 && !done2) || (!done1 && done2);
|
942
|
-
);
|
943
|
-
}
|
944
|
-
|
945
|
-
TEST_METHOD(35) {
|
946
|
-
// When spawning an app in the background, if it encountered an error
|
947
|
-
// it will remove the whole app group.
|
948
|
-
TempDirCopy c1("stub/rack", "rackapp.tmp");
|
949
|
-
PoolOptions options;
|
950
|
-
options.appRoot = "rackapp.tmp";
|
951
|
-
options.appType = "rack";
|
952
|
-
options.spawnMethod = "conservative";
|
953
|
-
options.printExceptions = false;
|
954
|
-
|
955
|
-
SessionPtr session1 = pool->get(options);
|
956
|
-
|
957
|
-
writeFile("rackapp.tmp/config.ru",
|
958
|
-
"raise 'foo'\n");
|
959
|
-
pool2->get(options);
|
960
|
-
|
961
|
-
EVENTUALLY(5,
|
962
|
-
result = pool->getCount() == 0u;
|
963
|
-
);
|
964
|
-
}
|
965
|
-
|
966
|
-
TEST_METHOD(36) {
|
967
|
-
// When cleaning, at least options.minProcesses processes should be kept around.
|
968
|
-
pool->setMaxIdleTime(0);
|
969
|
-
ApplicationPool::Ptr pool3 = newPoolConnection();
|
970
|
-
PoolOptions options;
|
971
|
-
options.appRoot = "stub/rack";
|
972
|
-
options.appType = "rack";
|
973
|
-
options.minProcesses = 2;
|
974
|
-
|
975
|
-
// Spawn 2 processes.
|
976
|
-
SessionPtr session1 = pool->get(options);
|
977
|
-
SessionPtr session2 = pool2->get(options);
|
978
|
-
session1.reset();
|
979
|
-
session2.reset();
|
980
|
-
EVENTUALLY(5,
|
981
|
-
result = pool->getActive() == 0u && pool->getCount() == 2u;
|
982
|
-
);
|
983
|
-
|
984
|
-
// Spawn another process, so we get 3.
|
985
|
-
session1 = pool->get(options);
|
986
|
-
session2 = pool2->get(options);
|
987
|
-
SessionPtr session3 = pool3->get(options);
|
988
|
-
session3.reset();
|
989
|
-
EVENTUALLY(5,
|
990
|
-
result = pool->getActive() == 2u && pool->getCount() == 3u;
|
991
|
-
);
|
992
|
-
|
993
|
-
// Now wait until one process is idle cleaned.
|
994
|
-
pool->setMaxIdleTime(1);
|
995
|
-
EVENTUALLY(10,
|
996
|
-
result = pool->getCount() == 2u;
|
997
|
-
);
|
998
|
-
}
|
999
|
-
|
1000
|
-
TEST_METHOD(37) {
|
1001
|
-
// Test whether processes are grouped together by appGroupName.
|
1002
|
-
TempDirCopy c1("stub/rack", "rackapp.tmp");
|
1003
|
-
PoolOptions options1;
|
1004
|
-
options1.appRoot = "rackapp.tmp";
|
1005
|
-
options1.appType = "rack";
|
1006
|
-
options1.appGroupName = "group A";
|
1007
|
-
SessionPtr session1 = pool->get(options1);
|
1008
|
-
|
1009
|
-
TempDirCopy c2("stub/rack", "rackapp2.tmp");
|
1010
|
-
PoolOptions options2;
|
1011
|
-
options2.appRoot = "rackapp2.tmp";
|
1012
|
-
options2.appType = "rack";
|
1013
|
-
options2.appGroupName = "group A";
|
1014
|
-
SessionPtr session2 = pool2->get(options2);
|
1015
|
-
|
1016
|
-
session1.reset();
|
1017
|
-
session2.reset();
|
1018
|
-
EVENTUALLY(5,
|
1019
|
-
result = pool->getCount() == 2u;
|
1020
|
-
);
|
1021
|
-
|
1022
|
-
touchFile("rackapp.tmp/tmp/restart.txt");
|
1023
|
-
session1 = pool->get(options1);
|
1024
|
-
ensure_equals(pool->getCount(), 1u);
|
1025
|
-
}
|
1026
|
-
|
1027
|
-
/*************************************/
|
1028
|
-
|
1029
|
-
#endif /* USE_TEMPLATE */
|