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.

Files changed (835) hide show
  1. data/DEVELOPERS.TXT +4 -10
  2. data/NEWS +19 -27
  3. data/Rakefile +20 -19
  4. data/bin/passenger +3 -2
  5. data/bin/passenger-config +35 -5
  6. data/bin/passenger-install-apache2-module +12 -12
  7. data/bin/passenger-install-nginx-module +55 -38
  8. data/bin/passenger-memory-stats +3 -1
  9. data/bin/passenger-status +7 -35
  10. data/build/agents.rb +107 -21
  11. data/build/apache2.rb +11 -46
  12. data/build/basics.rb +61 -9
  13. data/build/common_library.rb +59 -142
  14. data/build/cxx_tests.rb +111 -110
  15. data/build/documentation.rb +33 -0
  16. data/build/misc.rb +30 -12
  17. data/build/nginx.rb +10 -39
  18. data/build/oxt_tests.rb +1 -0
  19. data/build/ruby_extension.rb +1 -5
  20. data/build/test_basics.rb +3 -2
  21. data/dev/copy_boost_headers.rb +2 -1
  22. data/doc/Architectural overview.html +49 -90
  23. data/doc/DebuggingAndStressTesting.txt.md +49 -0
  24. data/doc/Packaging.txt.md +254 -0
  25. data/doc/Security of user switching support.html +35 -66
  26. data/doc/Users guide Apache.html +588 -758
  27. data/doc/Users guide Apache.idmap.txt +253 -136
  28. data/doc/Users guide Apache.txt +154 -109
  29. data/doc/Users guide Nginx.html +544 -660
  30. data/doc/Users guide Nginx.idmap.txt +179 -91
  31. data/doc/Users guide Nginx.txt +192 -118
  32. data/doc/Users guide Standalone.html +65 -48
  33. data/doc/Users guide Standalone.idmap.txt +10 -2
  34. data/doc/Users guide Standalone.txt +4 -0
  35. data/doc/images/glyphicons-halflings-white.png +0 -0
  36. data/doc/images/glyphicons-halflings.png +0 -0
  37. data/doc/images/phusion_banner_small.png +0 -0
  38. data/doc/images/{smart-lv2.png → smart.png} +0 -0
  39. data/doc/images/{smart-lv2.svg → smart.svg} +0 -0
  40. data/doc/templates/bootstrap.min.css +397 -0
  41. data/doc/templates/markdown.html.erb +117 -0
  42. data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +2 -1
  43. data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +26 -48
  44. data/doc/users_guide_snippets/passenger_spawn_method.txt +18 -30
  45. data/doc/users_guide_snippets/support_information.txt +30 -0
  46. data/ext/apache2/Bucket.cpp +9 -26
  47. data/ext/apache2/Bucket.h +13 -10
  48. data/ext/apache2/Configuration.cpp +70 -58
  49. data/ext/apache2/Configuration.hpp +19 -47
  50. data/ext/apache2/DirectoryMapper.h +7 -7
  51. data/ext/apache2/Hooks.cpp +150 -313
  52. data/ext/boost/algorithm/string/detail/case_conv.hpp +4 -2
  53. data/ext/boost/algorithm/string/detail/find_format.hpp +20 -20
  54. data/ext/boost/algorithm/string/detail/find_format_all.hpp +23 -23
  55. data/ext/boost/algorithm/string/detail/find_format_store.hpp +2 -2
  56. data/ext/boost/algorithm/string/detail/formatter.hpp +25 -0
  57. data/ext/boost/algorithm/string/formatter.hpp +20 -3
  58. data/ext/boost/assert.hpp +85 -4
  59. data/ext/boost/bind/bind.hpp +1 -1
  60. data/ext/boost/concept/detail/backward_compatibility.hpp +1 -1
  61. data/ext/boost/concept_check.hpp +140 -64
  62. data/ext/boost/config.hpp +1 -1
  63. data/ext/boost/config/auto_link.hpp +8 -6
  64. data/ext/boost/config/compiler/borland.hpp +12 -2
  65. data/ext/boost/config/compiler/clang.hpp +89 -30
  66. data/ext/boost/config/compiler/codegear.hpp +3 -2
  67. data/ext/boost/config/compiler/common_edg.hpp +7 -5
  68. data/ext/boost/config/compiler/cray.hpp +61 -0
  69. data/ext/boost/config/compiler/digitalmars.hpp +9 -1
  70. data/ext/boost/config/compiler/gcc.hpp +33 -24
  71. data/ext/boost/config/compiler/gcc_xml.hpp +4 -0
  72. data/ext/boost/config/compiler/hp_acc.hpp +12 -1
  73. data/ext/boost/config/compiler/intel.hpp +78 -4
  74. data/ext/boost/config/compiler/metrowerks.hpp +4 -1
  75. data/ext/boost/config/compiler/mpw.hpp +4 -1
  76. data/ext/boost/config/compiler/nvcc.hpp +8 -66
  77. data/ext/boost/config/compiler/pathscale.hpp +80 -0
  78. data/ext/boost/config/compiler/pgi.hpp +5 -5
  79. data/ext/boost/config/compiler/sunpro_cc.hpp +4 -1
  80. data/ext/boost/config/compiler/vacpp.hpp +37 -13
  81. data/ext/boost/config/compiler/visualc.hpp +24 -11
  82. data/ext/boost/config/platform/bsd.hpp +1 -1
  83. data/ext/boost/config/platform/cray.hpp +18 -0
  84. data/ext/boost/config/platform/cygwin.hpp +10 -0
  85. data/ext/boost/config/platform/linux.hpp +5 -0
  86. data/ext/boost/config/platform/macos.hpp +5 -4
  87. data/ext/boost/config/platform/symbian.hpp +5 -2
  88. data/ext/boost/config/platform/vms.hpp +25 -0
  89. data/ext/boost/config/platform/win32.hpp +7 -1
  90. data/ext/boost/config/select_compiler_config.hpp +8 -25
  91. data/ext/boost/config/select_platform_config.hpp +8 -1
  92. data/ext/boost/config/select_stdlib_config.hpp +9 -1
  93. data/ext/boost/config/stdlib/dinkumware.hpp +6 -9
  94. data/ext/boost/config/stdlib/libcomo.hpp +1 -4
  95. data/ext/boost/config/stdlib/libcpp.hpp +36 -0
  96. data/ext/boost/config/stdlib/libstdcpp3.hpp +37 -11
  97. data/ext/boost/config/stdlib/modena.hpp +1 -4
  98. data/ext/boost/config/stdlib/msl.hpp +1 -4
  99. data/ext/boost/config/stdlib/roguewave.hpp +9 -6
  100. data/ext/boost/config/stdlib/sgi.hpp +12 -4
  101. data/ext/boost/config/stdlib/stlport.hpp +11 -4
  102. data/ext/boost/config/stdlib/vacpp.hpp +11 -4
  103. data/ext/boost/config/suffix.hpp +71 -6
  104. data/ext/boost/config/warning_disable.hpp +1 -1
  105. data/ext/boost/container/container_fwd.hpp +177 -0
  106. data/ext/boost/cstdint.hpp +17 -12
  107. data/ext/boost/current_function.hpp +2 -1
  108. data/ext/boost/date_time/c_time.hpp +17 -1
  109. data/ext/boost/date_time/compiler_config.hpp +13 -15
  110. data/ext/boost/date_time/date_formatting.hpp +7 -1
  111. data/ext/boost/date_time/filetime_functions.hpp +4 -4
  112. data/ext/boost/date_time/gregorian_calendar.ipp +2 -2
  113. data/ext/boost/date_time/strings_from_facet.hpp +3 -3
  114. data/ext/boost/date_time/time_facet.hpp +101 -101
  115. data/ext/boost/detail/endian.hpp +4 -2
  116. data/ext/boost/detail/fenv.hpp +74 -0
  117. data/ext/boost/detail/sp_typeinfo.hpp +6 -0
  118. data/ext/boost/exception/detail/clone_current_exception.hpp +47 -0
  119. data/ext/boost/exception/detail/exception_ptr.hpp +194 -122
  120. data/ext/boost/exception/detail/type_info.hpp +3 -3
  121. data/ext/boost/exception/diagnostic_information.hpp +37 -21
  122. data/ext/boost/exception/exception.hpp +21 -1
  123. data/ext/boost/exception/info.hpp +0 -1
  124. data/ext/boost/function.hpp +2 -2
  125. data/ext/boost/function/function_base.hpp +15 -9
  126. data/ext/boost/function/function_template.hpp +26 -48
  127. data/ext/boost/integer_fwd.hpp +0 -16
  128. data/ext/boost/integer_traits.hpp +2 -2
  129. data/ext/boost/iterator.hpp +1 -1
  130. data/ext/boost/iterator/iterator_adaptor.hpp +1 -7
  131. data/ext/boost/iterator/iterator_facade.hpp +13 -13
  132. data/ext/boost/iterator/transform_iterator.hpp +5 -20
  133. data/ext/boost/lexical_cast.hpp +1655 -673
  134. data/ext/boost/math/policies/policy.hpp +982 -0
  135. data/ext/boost/math/special_functions/detail/fp_traits.hpp +570 -0
  136. data/ext/boost/math/special_functions/detail/round_fwd.hpp +80 -0
  137. data/ext/boost/math/special_functions/fpclassify.hpp +533 -0
  138. data/ext/boost/math/special_functions/math_fwd.hpp +1070 -0
  139. data/ext/boost/math/special_functions/sign.hpp +145 -0
  140. data/ext/boost/math/tools/config.hpp +321 -0
  141. data/ext/boost/math/tools/promotion.hpp +150 -0
  142. data/ext/boost/math/tools/real_cast.hpp +29 -0
  143. data/ext/boost/math/tools/user.hpp +97 -0
  144. data/ext/boost/move/move.hpp +1222 -0
  145. data/ext/boost/mpl/O1_size.hpp +40 -0
  146. data/ext/boost/mpl/O1_size_fwd.hpp +24 -0
  147. data/ext/boost/mpl/advance.hpp +76 -0
  148. data/ext/boost/mpl/advance_fwd.hpp +28 -0
  149. data/ext/boost/mpl/at.hpp +52 -0
  150. data/ext/boost/mpl/at_fwd.hpp +24 -0
  151. data/ext/boost/mpl/aux_/O1_size_impl.hpp +87 -0
  152. data/ext/boost/mpl/aux_/advance_backward.hpp +128 -0
  153. data/ext/boost/mpl/aux_/advance_forward.hpp +127 -0
  154. data/ext/boost/mpl/aux_/arithmetic_op.hpp +92 -0
  155. data/ext/boost/mpl/aux_/at_impl.hpp +45 -0
  156. data/ext/boost/mpl/aux_/begin_end_impl.hpp +101 -0
  157. data/ext/boost/mpl/aux_/clear_impl.hpp +35 -0
  158. data/ext/boost/mpl/aux_/comparison_op.hpp +83 -0
  159. data/ext/boost/mpl/aux_/config/forwarding.hpp +27 -0
  160. data/ext/boost/mpl/aux_/config/typeof.hpp +38 -0
  161. data/ext/boost/mpl/aux_/contains_impl.hpp +61 -0
  162. data/ext/boost/mpl/aux_/find_if_pred.hpp +31 -0
  163. data/ext/boost/mpl/aux_/fold_impl.hpp +43 -0
  164. data/ext/boost/mpl/aux_/has_begin.hpp +23 -0
  165. data/ext/boost/mpl/aux_/has_size.hpp +23 -0
  166. data/ext/boost/mpl/aux_/has_tag.hpp +23 -0
  167. data/ext/boost/mpl/aux_/inserter_algorithm.hpp +159 -0
  168. data/ext/boost/mpl/aux_/is_msvc_eti_arg.hpp +64 -0
  169. data/ext/boost/mpl/aux_/iter_apply.hpp +47 -0
  170. data/ext/boost/mpl/aux_/iter_fold_if_impl.hpp +210 -0
  171. data/ext/boost/mpl/aux_/iter_fold_impl.hpp +42 -0
  172. data/ext/boost/mpl/aux_/lambda_spec.hpp +49 -0
  173. data/ext/boost/mpl/aux_/largest_int.hpp +63 -0
  174. data/ext/boost/mpl/aux_/msvc_eti_base.hpp +77 -0
  175. data/ext/boost/mpl/aux_/msvc_type.hpp +62 -0
  176. data/ext/boost/mpl/aux_/numeric_cast_utils.hpp +77 -0
  177. data/ext/boost/mpl/aux_/numeric_op.hpp +315 -0
  178. data/ext/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp +97 -0
  179. data/ext/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp +97 -0
  180. data/ext/boost/mpl/aux_/preprocessed/gcc/equal_to.hpp +94 -0
  181. data/ext/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp +180 -0
  182. data/ext/boost/mpl/aux_/preprocessed/gcc/greater.hpp +94 -0
  183. data/ext/boost/mpl/aux_/preprocessed/gcc/greater_equal.hpp +94 -0
  184. data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp +133 -0
  185. data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp +180 -0
  186. data/ext/boost/mpl/aux_/preprocessed/gcc/less.hpp +94 -0
  187. data/ext/boost/mpl/aux_/preprocessed/gcc/less_equal.hpp +94 -0
  188. data/ext/boost/mpl/aux_/preprocessed/gcc/list.hpp +323 -0
  189. data/ext/boost/mpl/aux_/preprocessed/gcc/minus.hpp +146 -0
  190. data/ext/boost/mpl/aux_/preprocessed/gcc/not_equal_to.hpp +94 -0
  191. data/ext/boost/mpl/aux_/preprocessed/gcc/plus.hpp +146 -0
  192. data/ext/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp +231 -0
  193. data/ext/boost/mpl/aux_/preprocessed/gcc/times.hpp +146 -0
  194. data/ext/boost/mpl/aux_/preprocessed/gcc/vector.hpp +323 -0
  195. data/ext/boost/mpl/aux_/preprocessor/default_params.hpp +67 -0
  196. data/ext/boost/mpl/aux_/push_back_impl.hpp +70 -0
  197. data/ext/boost/mpl/aux_/push_front_impl.hpp +71 -0
  198. data/ext/boost/mpl/aux_/reverse_fold_impl.hpp +44 -0
  199. data/ext/boost/mpl/aux_/size_impl.hpp +52 -0
  200. data/ext/boost/mpl/aux_/traits_lambda_spec.hpp +63 -0
  201. data/ext/boost/mpl/back_fwd.hpp +24 -0
  202. data/ext/boost/mpl/back_inserter.hpp +34 -0
  203. data/ext/boost/mpl/begin_end.hpp +57 -0
  204. data/ext/boost/mpl/begin_end_fwd.hpp +27 -0
  205. data/ext/boost/mpl/clear.hpp +39 -0
  206. data/ext/boost/mpl/clear_fwd.hpp +24 -0
  207. data/ext/boost/mpl/comparison.hpp +24 -0
  208. data/ext/boost/mpl/contains.hpp +41 -0
  209. data/ext/boost/mpl/contains_fwd.hpp +25 -0
  210. data/ext/boost/mpl/deref.hpp +41 -0
  211. data/ext/boost/mpl/distance.hpp +78 -0
  212. data/ext/boost/mpl/distance_fwd.hpp +28 -0
  213. data/ext/boost/mpl/empty_fwd.hpp +24 -0
  214. data/ext/boost/mpl/equal_to.hpp +21 -0
  215. data/ext/boost/mpl/find.hpp +38 -0
  216. data/ext/boost/mpl/find_if.hpp +50 -0
  217. data/ext/boost/mpl/fold.hpp +48 -0
  218. data/ext/boost/mpl/front_fwd.hpp +24 -0
  219. data/ext/boost/mpl/front_inserter.hpp +33 -0
  220. data/ext/boost/mpl/greater.hpp +21 -0
  221. data/ext/boost/mpl/greater_equal.hpp +21 -0
  222. data/ext/boost/mpl/inserter.hpp +32 -0
  223. data/ext/boost/mpl/iter_fold.hpp +49 -0
  224. data/ext/boost/mpl/iter_fold_if.hpp +117 -0
  225. data/ext/boost/mpl/iterator_range.hpp +42 -0
  226. data/ext/boost/mpl/iterator_tags.hpp +27 -0
  227. data/ext/boost/mpl/less.hpp +21 -0
  228. data/ext/boost/mpl/less_equal.hpp +21 -0
  229. data/ext/boost/mpl/limits/list.hpp +21 -0
  230. data/ext/boost/mpl/limits/vector.hpp +21 -0
  231. data/ext/boost/mpl/list.hpp +57 -0
  232. data/ext/boost/mpl/list/aux_/O1_size.hpp +33 -0
  233. data/ext/boost/mpl/list/aux_/begin_end.hpp +44 -0
  234. data/ext/boost/mpl/list/aux_/clear.hpp +34 -0
  235. data/ext/boost/mpl/list/aux_/empty.hpp +34 -0
  236. data/ext/boost/mpl/list/aux_/front.hpp +33 -0
  237. data/ext/boost/mpl/list/aux_/include_preprocessed.hpp +35 -0
  238. data/ext/boost/mpl/list/aux_/item.hpp +55 -0
  239. data/ext/boost/mpl/list/aux_/iterator.hpp +76 -0
  240. data/ext/boost/mpl/list/aux_/pop_front.hpp +34 -0
  241. data/ext/boost/mpl/list/aux_/preprocessed/plain/list10.hpp +149 -0
  242. data/ext/boost/mpl/list/aux_/preprocessed/plain/list20.hpp +169 -0
  243. data/ext/boost/mpl/list/aux_/push_back.hpp +36 -0
  244. data/ext/boost/mpl/list/aux_/push_front.hpp +39 -0
  245. data/ext/boost/mpl/list/aux_/size.hpp +33 -0
  246. data/ext/boost/mpl/list/aux_/tag.hpp +24 -0
  247. data/ext/boost/mpl/list/list0.hpp +42 -0
  248. data/ext/boost/mpl/list/list10.hpp +43 -0
  249. data/ext/boost/mpl/list/list20.hpp +43 -0
  250. data/ext/boost/mpl/long.hpp +22 -0
  251. data/ext/boost/mpl/long_fwd.hpp +27 -0
  252. data/ext/boost/mpl/minus.hpp +21 -0
  253. data/ext/boost/mpl/multiplies.hpp +53 -0
  254. data/ext/boost/mpl/negate.hpp +81 -0
  255. data/ext/boost/mpl/not_equal_to.hpp +21 -0
  256. data/ext/boost/mpl/numeric_cast.hpp +41 -0
  257. data/ext/boost/mpl/pair.hpp +70 -0
  258. data/ext/boost/mpl/plus.hpp +21 -0
  259. data/ext/boost/mpl/pop_back_fwd.hpp +24 -0
  260. data/ext/boost/mpl/pop_front_fwd.hpp +24 -0
  261. data/ext/boost/mpl/prior.hpp +19 -0
  262. data/ext/boost/mpl/push_back.hpp +53 -0
  263. data/ext/boost/mpl/push_back_fwd.hpp +24 -0
  264. data/ext/boost/mpl/push_front.hpp +52 -0
  265. data/ext/boost/mpl/push_front_fwd.hpp +24 -0
  266. data/ext/boost/mpl/remove_if.hpp +83 -0
  267. data/ext/boost/mpl/reverse_fold.hpp +50 -0
  268. data/ext/boost/mpl/same_as.hpp +55 -0
  269. data/ext/boost/mpl/sequence_tag.hpp +124 -0
  270. data/ext/boost/mpl/sequence_tag_fwd.hpp +26 -0
  271. data/ext/boost/mpl/size.hpp +42 -0
  272. data/ext/boost/mpl/size_fwd.hpp +24 -0
  273. data/ext/boost/mpl/tag.hpp +52 -0
  274. data/ext/boost/mpl/times.hpp +21 -0
  275. data/ext/boost/mpl/vector.hpp +57 -0
  276. data/ext/boost/mpl/vector/aux_/O1_size.hpp +56 -0
  277. data/ext/boost/mpl/vector/aux_/at.hpp +116 -0
  278. data/ext/boost/mpl/vector/aux_/back.hpp +59 -0
  279. data/ext/boost/mpl/vector/aux_/begin_end.hpp +49 -0
  280. data/ext/boost/mpl/vector/aux_/clear.hpp +55 -0
  281. data/ext/boost/mpl/vector/aux_/empty.hpp +68 -0
  282. data/ext/boost/mpl/vector/aux_/front.hpp +56 -0
  283. data/ext/boost/mpl/vector/aux_/include_preprocessed.hpp +55 -0
  284. data/ext/boost/mpl/vector/aux_/item.hpp +103 -0
  285. data/ext/boost/mpl/vector/aux_/iterator.hpp +130 -0
  286. data/ext/boost/mpl/vector/aux_/pop_back.hpp +40 -0
  287. data/ext/boost/mpl/vector/aux_/pop_front.hpp +40 -0
  288. data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp +829 -0
  289. data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp +1144 -0
  290. data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp +139 -0
  291. data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp +159 -0
  292. data/ext/boost/mpl/vector/aux_/push_back.hpp +40 -0
  293. data/ext/boost/mpl/vector/aux_/push_front.hpp +40 -0
  294. data/ext/boost/mpl/vector/aux_/size.hpp +49 -0
  295. data/ext/boost/mpl/vector/aux_/tag.hpp +32 -0
  296. data/ext/boost/mpl/vector/aux_/vector0.hpp +52 -0
  297. data/ext/boost/mpl/vector/vector0.hpp +34 -0
  298. data/ext/boost/mpl/vector/vector10.hpp +45 -0
  299. data/ext/boost/mpl/vector/vector20.hpp +45 -0
  300. data/ext/boost/none.hpp +1 -1
  301. data/ext/boost/numeric/conversion/bounds.hpp +24 -0
  302. data/ext/boost/numeric/conversion/cast.hpp +61 -0
  303. data/ext/boost/numeric/conversion/conversion_traits.hpp +39 -0
  304. data/ext/boost/numeric/conversion/converter.hpp +68 -0
  305. data/ext/boost/numeric/conversion/converter_policies.hpp +186 -0
  306. data/ext/boost/numeric/conversion/detail/bounds.hpp +58 -0
  307. data/ext/boost/numeric/conversion/detail/conversion_traits.hpp +97 -0
  308. data/ext/boost/numeric/conversion/detail/converter.hpp +602 -0
  309. data/ext/boost/numeric/conversion/detail/int_float_mixture.hpp +72 -0
  310. data/ext/boost/numeric/conversion/detail/is_subranged.hpp +234 -0
  311. data/ext/boost/numeric/conversion/detail/meta.hpp +120 -0
  312. data/ext/boost/numeric/conversion/detail/numeric_cast_traits.hpp +138 -0
  313. data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_common.hpp +1741 -0
  314. data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_long_long.hpp +347 -0
  315. data/ext/boost/numeric/conversion/detail/sign_mixture.hpp +72 -0
  316. data/ext/boost/numeric/conversion/detail/udt_builtin_mixture.hpp +69 -0
  317. data/ext/boost/numeric/conversion/int_float_mixture_enum.hpp +29 -0
  318. data/ext/boost/numeric/conversion/numeric_cast_traits.hpp +31 -0
  319. data/ext/boost/numeric/conversion/sign_mixture_enum.hpp +29 -0
  320. data/ext/boost/numeric/conversion/udt_builtin_mixture_enum.hpp +26 -0
  321. data/ext/boost/operators.hpp +3 -1
  322. data/ext/boost/optional/optional.hpp +146 -79
  323. data/ext/boost/optional/optional_fwd.hpp +8 -1
  324. data/ext/boost/preprocessor/cat.hpp +2 -2
  325. data/ext/boost/preprocessor/config/config.hpp +39 -4
  326. data/ext/boost/preprocessor/facilities/intercept.hpp +277 -0
  327. data/ext/boost/preprocessor/facilities/overload.hpp +25 -0
  328. data/ext/boost/preprocessor/iteration/detail/iter/forward1.hpp +3 -3
  329. data/ext/boost/preprocessor/iteration/iterate.hpp +3 -3
  330. data/ext/boost/preprocessor/punctuation/paren.hpp +23 -0
  331. data/ext/boost/preprocessor/repetition/enum_shifted_params.hpp +44 -0
  332. data/ext/boost/preprocessor/seq/cat.hpp +5 -4
  333. data/ext/boost/preprocessor/seq/size.hpp +0 -1
  334. data/ext/boost/preprocessor/tuple/eat.hpp +83 -34
  335. data/ext/boost/preprocessor/tuple/elem.hpp +161 -355
  336. data/ext/boost/preprocessor/tuple/rem.hpp +110 -48
  337. data/ext/boost/preprocessor/tuple/to_list.hpp +90 -36
  338. data/ext/boost/preprocessor/variadic/elem.hpp +94 -0
  339. data/ext/boost/preprocessor/variadic/size.hpp +30 -0
  340. data/ext/boost/range/begin.hpp +17 -6
  341. data/ext/boost/range/concepts.hpp +37 -2
  342. data/ext/boost/range/detail/safe_bool.hpp +72 -0
  343. data/ext/boost/range/end.hpp +14 -9
  344. data/ext/boost/range/iterator_range_core.hpp +120 -12
  345. data/ext/boost/range/size.hpp +21 -5
  346. data/ext/boost/smart_ptr/detail/shared_count.hpp +88 -0
  347. data/ext/boost/smart_ptr/detail/sp_counted_base.hpp +3 -0
  348. data/ext/boost/smart_ptr/detail/sp_counted_base_aix.hpp +142 -0
  349. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +9 -0
  350. data/ext/boost/smart_ptr/detail/sp_counted_impl.hpp +10 -2
  351. data/ext/boost/smart_ptr/detail/sp_has_sync.hpp +5 -1
  352. data/ext/boost/smart_ptr/detail/spinlock.hpp +4 -1
  353. data/ext/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +20 -3
  354. data/ext/boost/smart_ptr/detail/spinlock_pool.hpp +4 -0
  355. data/ext/boost/smart_ptr/make_shared.hpp +591 -22
  356. data/ext/boost/smart_ptr/shared_array.hpp +29 -1
  357. data/ext/boost/smart_ptr/shared_ptr.hpp +29 -13
  358. data/ext/boost/smart_ptr/weak_ptr.hpp +24 -12
  359. data/ext/boost/src/pthread/once.cpp +9 -7
  360. data/ext/boost/src/pthread/thread.cpp +32 -28
  361. data/ext/boost/src/pthread/timeconv.inl +4 -5
  362. data/ext/boost/src/tss_null.cpp +5 -1
  363. data/ext/boost/static_assert.hpp +8 -2
  364. data/ext/boost/thread/detail/config.hpp +19 -4
  365. data/ext/boost/thread/detail/move.hpp +11 -5
  366. data/ext/boost/thread/detail/thread.hpp +59 -43
  367. data/ext/boost/thread/exceptions.hpp +9 -9
  368. data/ext/boost/thread/future.hpp +150 -82
  369. data/ext/boost/thread/locks.hpp +101 -60
  370. data/ext/boost/thread/pthread/condition_variable.hpp +79 -32
  371. data/ext/boost/thread/pthread/condition_variable_fwd.hpp +12 -3
  372. data/ext/boost/thread/pthread/mutex.hpp +17 -14
  373. data/ext/boost/thread/pthread/once.hpp +3 -4
  374. data/ext/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +12 -2
  375. data/ext/boost/thread/pthread/recursive_mutex.hpp +19 -19
  376. data/ext/boost/thread/pthread/shared_mutex.hpp +13 -13
  377. data/ext/boost/thread/pthread/thread_data.hpp +40 -12
  378. data/ext/boost/thread/thread_time.hpp +5 -0
  379. data/ext/boost/throw_exception.hpp +1 -1
  380. data/ext/boost/token_functions.hpp +34 -10
  381. data/ext/boost/type_traits/add_rvalue_reference.hpp +66 -0
  382. data/ext/boost/type_traits/alignment_of.hpp +1 -1
  383. data/ext/boost/type_traits/detail/bool_trait_def.hpp +26 -3
  384. data/ext/boost/type_traits/detail/bool_trait_undef.hpp +3 -2
  385. data/ext/boost/type_traits/detail/cv_traits_impl.hpp +1 -1
  386. data/ext/boost/type_traits/detail/size_t_trait_def.hpp +6 -4
  387. data/ext/boost/type_traits/detail/type_trait_def.hpp +8 -2
  388. data/ext/boost/type_traits/function_traits.hpp +1 -1
  389. data/ext/boost/type_traits/has_nothrow_constructor.hpp +53 -0
  390. data/ext/boost/type_traits/has_nothrow_copy.hpp +19 -5
  391. data/ext/boost/type_traits/has_trivial_constructor.hpp +51 -0
  392. data/ext/boost/type_traits/has_trivial_copy.hpp +20 -5
  393. data/ext/boost/type_traits/has_trivial_destructor.hpp +12 -5
  394. data/ext/boost/type_traits/intrinsics.hpp +119 -71
  395. data/ext/boost/type_traits/is_const.hpp +5 -5
  396. data/ext/boost/type_traits/is_convertible.hpp +14 -13
  397. data/ext/boost/type_traits/is_enum.hpp +1 -1
  398. data/ext/boost/type_traits/is_floating_point.hpp +27 -0
  399. data/ext/boost/type_traits/is_function.hpp +3 -3
  400. data/ext/boost/type_traits/is_fundamental.hpp +1 -1
  401. data/ext/boost/type_traits/is_member_function_pointer.hpp +2 -2
  402. data/ext/boost/type_traits/is_member_pointer.hpp +2 -2
  403. data/ext/boost/type_traits/is_pod.hpp +11 -3
  404. data/ext/boost/type_traits/is_pointer.hpp +2 -2
  405. data/ext/boost/type_traits/is_signed.hpp +8 -3
  406. data/ext/boost/type_traits/is_union.hpp +8 -0
  407. data/ext/boost/type_traits/is_unsigned.hpp +9 -4
  408. data/ext/boost/type_traits/is_volatile.hpp +5 -5
  409. data/ext/boost/type_traits/remove_cv.hpp +4 -3
  410. data/ext/boost/type_traits/remove_pointer.hpp +51 -2
  411. data/ext/boost/type_traits/remove_reference.hpp +2 -2
  412. data/ext/boost/type_traits/type_with_alignment.hpp +8 -2
  413. data/ext/boost/utility/declval.hpp +44 -0
  414. data/ext/boost/utility/detail/in_place_factory_prefix.hpp +36 -0
  415. data/ext/boost/utility/detail/in_place_factory_suffix.hpp +23 -0
  416. data/ext/boost/utility/detail/result_of_iterate.hpp +142 -0
  417. data/ext/boost/utility/in_place_factory.hpp +88 -0
  418. data/ext/boost/utility/result_of.hpp +103 -0
  419. data/ext/boost/utility/swap.hpp +55 -0
  420. data/ext/common/AnsiColorConstants.h +36 -0
  421. data/ext/common/ApplicationPool2/Common.h +87 -0
  422. data/ext/common/ApplicationPool2/ComponentInfo.h +53 -0
  423. data/ext/common/ApplicationPool2/Group.h +648 -0
  424. data/ext/common/ApplicationPool2/Implementation.cpp +580 -0
  425. data/ext/common/ApplicationPool2/Options.h +576 -0
  426. data/ext/common/ApplicationPool2/PipeWatcher.h +61 -0
  427. data/ext/common/ApplicationPool2/Pool.h +1181 -0
  428. data/ext/common/ApplicationPool2/Process.h +425 -0
  429. data/ext/common/ApplicationPool2/README.md +96 -0
  430. data/ext/common/ApplicationPool2/Session.h +158 -0
  431. data/ext/common/ApplicationPool2/Socket.h +246 -0
  432. data/ext/common/ApplicationPool2/Spawner.h +2212 -0
  433. data/ext/common/ApplicationPool2/SuperGroup.h +749 -0
  434. data/ext/common/BackgroundEventLoop.cpp +129 -0
  435. data/ext/common/BackgroundEventLoop.h +61 -0
  436. data/ext/common/Constants.h +3 -1
  437. data/ext/common/EventedBufferedInput.h +331 -0
  438. data/ext/common/EventedMessageServer.h +17 -34
  439. data/ext/common/EventedServer.h +2 -2
  440. data/ext/common/Exceptions.h +71 -19
  441. data/ext/common/FileDescriptor.h +8 -6
  442. data/ext/common/HttpConstants.h +167 -0
  443. data/ext/common/IniFile.h +24 -0
  444. data/ext/common/Logging.h +62 -849
  445. data/ext/common/MessageReadersWriters.h +19 -0
  446. data/ext/common/MessageServer.h +11 -14
  447. data/ext/common/MultiLibeio.cpp +198 -0
  448. data/ext/common/MultiLibeio.h +67 -0
  449. data/ext/common/ResourceLocator.h +24 -41
  450. data/ext/common/SafeLibev.h +186 -14
  451. data/ext/common/StaticString.h +23 -3
  452. data/ext/common/UnionStation.h +972 -0
  453. data/ext/common/Utils.cpp +168 -24
  454. data/ext/common/Utils.h +25 -3
  455. data/ext/common/Utils/CachedFileStat.hpp +4 -3
  456. data/ext/common/Utils/FileChangeChecker.h +2 -2
  457. data/ext/common/Utils/HashMap.h +50 -0
  458. data/ext/common/Utils/IOUtils.cpp +229 -68
  459. data/ext/common/Utils/IOUtils.h +134 -3
  460. data/ext/common/Utils/Lock.h +28 -0
  461. data/ext/common/Utils/MemoryBarrier.h +52 -0
  462. data/ext/common/Utils/PriorityQueue.h +54 -0
  463. data/ext/common/Utils/ProcessMetricsCollector.h +9 -11
  464. data/ext/common/Utils/ScopeGuard.h +50 -1
  465. data/ext/common/Utils/SmallVector.h +653 -0
  466. data/ext/common/Utils/StrIntUtils.cpp +26 -2
  467. data/ext/common/Utils/StrIntUtils.h +18 -2
  468. data/ext/common/Utils/StringMap.h +125 -8
  469. data/ext/common/Utils/Template.h +212 -0
  470. data/ext/common/Utils/fib.c +699 -0
  471. data/ext/common/Utils/fib.h +101 -0
  472. data/ext/common/Utils/fibpriv.h +67 -0
  473. data/ext/common/Utils/json-forwards.h +249 -0
  474. data/ext/common/Utils/json.h +1855 -0
  475. data/ext/common/Utils/jsoncpp.cpp +4230 -0
  476. data/ext/common/agents/Base.cpp +1126 -0
  477. data/ext/common/{AgentBase.h → agents/Base.h} +5 -1
  478. data/ext/common/agents/EnvPrinter.c +16 -0
  479. data/ext/common/agents/HelperAgent/AgentOptions.h +81 -0
  480. data/ext/common/{HelperAgent → agents/HelperAgent}/BacktracesServer.h +3 -2
  481. data/ext/common/agents/HelperAgent/FileBackedPipe.h +732 -0
  482. data/ext/common/agents/HelperAgent/Main.cpp +497 -0
  483. data/ext/common/agents/HelperAgent/RequestHandler.cpp +283 -0
  484. data/ext/common/agents/HelperAgent/RequestHandler.h +2139 -0
  485. data/ext/common/agents/HelperAgent/ScgiRequestParser.h +451 -0
  486. data/ext/common/{LoggingAgent → agents/LoggingAgent}/DataStoreId.h +1 -1
  487. data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.cpp +1 -1
  488. data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.h +0 -0
  489. data/ext/common/{LoggingAgent → agents/LoggingAgent}/LoggingServer.h +18 -16
  490. data/ext/common/{LoggingAgent → agents/LoggingAgent}/Main.cpp +15 -13
  491. data/ext/common/{LoggingAgent → agents/LoggingAgent}/RemoteSender.h +6 -6
  492. data/ext/common/agents/SpawnPreparer.cpp +127 -0
  493. data/ext/common/{Watchdog.cpp → agents/Watchdog/Main.cpp} +63 -25
  494. data/ext/libeio/Changes +72 -0
  495. data/ext/{google/COPYING → libeio/LICENSE} +17 -9
  496. data/ext/libeio/Makefile.am +15 -0
  497. data/ext/libeio/Makefile.in +694 -0
  498. data/ext/libeio/aclocal.m4 +9418 -0
  499. data/ext/libeio/autogen.sh +3 -0
  500. data/ext/libeio/config.guess +1501 -0
  501. data/ext/libeio/config.h.in +136 -0
  502. data/ext/libeio/config.sub +1705 -0
  503. data/ext/libeio/configure +14822 -0
  504. data/ext/libeio/configure.ac +22 -0
  505. data/ext/libeio/demo.c +194 -0
  506. data/ext/libeio/ecb.h +457 -0
  507. data/ext/libeio/eio.c +2816 -0
  508. data/ext/libeio/eio.h +411 -0
  509. data/ext/libeio/install-sh +520 -0
  510. data/ext/libeio/libeio.m4 +211 -0
  511. data/ext/libeio/ltmain.sh +9636 -0
  512. data/ext/libeio/missing +376 -0
  513. data/ext/libeio/xthread.h +166 -0
  514. data/ext/libev/Changes +125 -7
  515. data/ext/libev/Makefile.am +5 -3
  516. data/ext/libev/Makefile.in +209 -120
  517. data/ext/libev/aclocal.m4 +6027 -4619
  518. data/ext/libev/autogen.sh +1 -4
  519. data/ext/libev/config.h.in +11 -7
  520. data/ext/libev/configure +7312 -14993
  521. data/ext/libev/configure.ac +12 -5
  522. data/ext/libev/depcomp +630 -0
  523. data/ext/libev/ev++.h +48 -32
  524. data/ext/libev/ev.c +1173 -391
  525. data/ext/libev/ev.h +315 -181
  526. data/ext/libev/ev_epoll.c +66 -15
  527. data/ext/libev/ev_kqueue.c +20 -18
  528. data/ext/libev/ev_poll.c +27 -23
  529. data/ext/libev/ev_port.c +39 -19
  530. data/ext/libev/ev_select.c +23 -17
  531. data/ext/libev/ev_vars.h +25 -8
  532. data/ext/libev/ev_win32.c +6 -6
  533. data/ext/libev/ev_wrap.h +22 -2
  534. data/ext/libev/event.c +18 -17
  535. data/ext/libev/event.h +16 -4
  536. data/ext/libev/libev.m4 +10 -6
  537. data/ext/libev/ltmain.sh +7353 -5811
  538. data/ext/nginx/Configuration.c +74 -42
  539. data/ext/nginx/Configuration.h +3 -5
  540. data/ext/nginx/ContentHandler.c +26 -83
  541. data/ext/nginx/ContentHandler.h +1 -1
  542. data/ext/nginx/config +13 -9
  543. data/ext/nginx/ngx_http_passenger_module.c +3 -7
  544. data/ext/oxt/detail/backtrace_enabled.hpp +5 -102
  545. data/ext/oxt/detail/context.hpp +90 -0
  546. data/ext/oxt/detail/spin_lock_darwin.hpp +4 -0
  547. data/ext/oxt/detail/spin_lock_gcc_x86.hpp +4 -0
  548. data/ext/oxt/detail/spin_lock_pthreads.hpp +14 -0
  549. data/ext/oxt/detail/tracable_exception_enabled.hpp +2 -2
  550. data/ext/oxt/dynamic_thread_group.hpp +27 -1
  551. data/ext/oxt/implementation.cpp +415 -0
  552. data/ext/oxt/{thread.cpp → initialize.hpp} +13 -6
  553. data/ext/oxt/macros.hpp +32 -1
  554. data/ext/oxt/spin_lock.hpp +6 -11
  555. data/ext/oxt/system_calls.cpp +204 -16
  556. data/ext/oxt/system_calls.hpp +85 -45
  557. data/ext/oxt/thread.hpp +13 -117
  558. data/ext/ruby/passenger_native_support.c +82 -237
  559. data/helper-scripts/backtrace-sanitizer.rb +114 -0
  560. data/helper-scripts/classic-rails-loader.rb +135 -0
  561. data/helper-scripts/classic-rails-preloader.rb +161 -0
  562. data/helper-scripts/node-loader.js +314 -0
  563. data/helper-scripts/rack-loader.rb +104 -0
  564. data/helper-scripts/rack-preloader.rb +132 -0
  565. data/helper-scripts/wsgi-loader.py +231 -0
  566. data/helper-scripts/wsgi-preloader.py +1 -0
  567. data/lib/phusion_passenger.rb +159 -61
  568. data/lib/phusion_passenger/abstract_installer.rb +182 -87
  569. data/lib/phusion_passenger/admin_tools/server_instance.rb +25 -19
  570. data/lib/phusion_passenger/analytics_logger.rb +5 -4
  571. data/lib/phusion_passenger/classic_rails/{request_handler.rb → thread_handler_extension.rb} +4 -40
  572. data/lib/phusion_passenger/classic_rails_extensions/init.rb +5 -3
  573. data/lib/phusion_passenger/common_library.rb +441 -0
  574. data/lib/phusion_passenger/console_text_template.rb +4 -16
  575. data/lib/phusion_passenger/constants.rb +1 -8
  576. data/lib/phusion_passenger/debug_logging.rb +5 -2
  577. data/lib/phusion_passenger/dependencies.rb +51 -13
  578. data/lib/phusion_passenger/loader_shared_helpers.rb +318 -0
  579. data/lib/phusion_passenger/message_channel.rb +3 -47
  580. data/lib/phusion_passenger/message_client.rb +2 -2
  581. data/lib/phusion_passenger/native_support.rb +36 -15
  582. data/lib/phusion_passenger/packaging.rb +8 -11
  583. data/lib/phusion_passenger/platform_info.rb +25 -17
  584. data/lib/phusion_passenger/platform_info/apache.rb +10 -7
  585. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +10 -30
  586. data/lib/phusion_passenger/platform_info/compiler.rb +93 -34
  587. data/lib/phusion_passenger/platform_info/ruby.rb +37 -97
  588. data/lib/phusion_passenger/preloader_shared_helpers.rb +121 -0
  589. data/lib/phusion_passenger/public_api.rb +1 -4
  590. data/lib/phusion_passenger/rack/{request_handler.rb → thread_handler_extension.rb} +14 -63
  591. data/lib/phusion_passenger/rails3_extensions/init.rb +9 -8
  592. data/lib/phusion_passenger/request_handler.rb +500 -0
  593. data/lib/phusion_passenger/request_handler/thread_handler.rb +360 -0
  594. data/lib/phusion_passenger/ruby_core_enhancements.rb +142 -0
  595. data/lib/phusion_passenger/standalone/command.rb +36 -15
  596. data/lib/phusion_passenger/standalone/package_runtime_command.rb +16 -8
  597. data/lib/phusion_passenger/standalone/runtime_installer.rb +169 -72
  598. data/lib/phusion_passenger/standalone/start_command.rb +44 -39
  599. data/lib/phusion_passenger/standalone/utils.rb +5 -5
  600. data/lib/phusion_passenger/utils.rb +35 -914
  601. data/lib/phusion_passenger/utils/ansi_colors.rb +59 -0
  602. data/lib/phusion_passenger/utils/file_system_watcher.rb +1 -1
  603. data/lib/phusion_passenger/utils/robust_interruption.rb +134 -0
  604. data/lib/phusion_passenger/utils/tee_input.rb +174 -0
  605. data/lib/phusion_passenger/utils/tmpio.rb +33 -0
  606. data/lib/phusion_passenger/utils/unseekable_socket.rb +6 -0
  607. data/resources/mime.types +5 -1
  608. data/{lib/phusion_passenger/templates → resources}/standalone_default_root/index.html +0 -0
  609. data/{lib/phusion_passenger → resources}/templates/apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
  610. data/{lib/phusion_passenger → resources}/templates/apache2/config_snippets.txt.erb +0 -0
  611. data/{lib/phusion_passenger → resources}/templates/apache2/deployment_example.txt.erb +0 -0
  612. data/{lib/phusion_passenger → resources}/templates/apache2/no_write_permission_to_passenger_root.txt.erb +0 -0
  613. data/{lib/phusion_passenger → resources}/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
  614. data/{lib/phusion_passenger → resources}/templates/apache2/run_installer_as_root.txt.erb +0 -0
  615. data/{lib/phusion_passenger → resources}/templates/apache2/welcome.txt.erb +0 -0
  616. data/{lib/phusion_passenger → resources}/templates/error_layout.css +6 -0
  617. data/resources/templates/error_layout.html.template +89 -0
  618. data/resources/templates/general_error.html.template +1 -0
  619. data/resources/templates/general_error_with_html.html.template +1 -0
  620. data/{lib/phusion_passenger → resources}/templates/nginx/ask_for_extra_configure_flags.txt.erb +0 -0
  621. data/{lib/phusion_passenger → resources}/templates/nginx/cannot_write_to_dir.txt.erb +0 -0
  622. data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets.txt.erb +0 -0
  623. data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets_inserted.txt.erb +0 -0
  624. data/{lib/phusion_passenger → resources}/templates/nginx/confirm_extra_configure_flags.txt.erb +0 -0
  625. data/{lib/phusion_passenger → resources}/templates/nginx/deployment_example.txt.erb +0 -0
  626. data/resources/templates/nginx/not_available_when_natively_packaged.txt.erb +8 -0
  627. data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_downloaded.txt.erb +0 -0
  628. data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_extracted.txt.erb +0 -0
  629. data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
  630. data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
  631. data/{lib/phusion_passenger → resources}/templates/nginx/query_download_and_install.txt.erb +0 -0
  632. data/{lib/phusion_passenger → resources}/templates/nginx/run_installer_as_root.txt.erb +0 -0
  633. data/{lib/phusion_passenger → resources}/templates/nginx/welcome.txt.erb +0 -0
  634. data/{lib/phusion_passenger → resources}/templates/standalone/cannot_write_to_dir.txt.erb +0 -0
  635. data/{lib/phusion_passenger → resources}/templates/standalone/config.erb +26 -5
  636. data/{lib/phusion_passenger → resources}/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
  637. data/{lib/phusion_passenger → resources}/templates/standalone/run_installer_as_root.txt.erb +0 -0
  638. data/{lib/phusion_passenger → resources}/templates/standalone/welcome.txt.erb +0 -0
  639. data/resources/templates/undisclosed_error.html.template +25 -0
  640. data/test/config.json.example +42 -0
  641. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +86 -0
  642. data/test/cxx/ApplicationPool2/OptionsTest.cpp +44 -0
  643. data/test/cxx/ApplicationPool2/PoolTest.cpp +1234 -0
  644. data/test/cxx/ApplicationPool2/ProcessTest.cpp +131 -0
  645. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +229 -0
  646. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +744 -0
  647. data/test/cxx/BufferedIOTest.cpp +7 -7
  648. data/test/cxx/CxxTestMain.cpp +65 -2
  649. data/test/cxx/FileBackedPipeTest.cpp +626 -0
  650. data/test/cxx/FileChangeCheckerTest.cpp +20 -18
  651. data/test/cxx/FilterSupportTest.cpp +5 -5
  652. data/test/cxx/IOUtilsTest.cpp +11 -4
  653. data/test/cxx/MessageReadersWritersTest.cpp +1 -1
  654. data/test/cxx/MessageServerTest.cpp +31 -30
  655. data/test/cxx/RequestHandlerTest.cpp +777 -0
  656. data/test/cxx/ScgiRequestParserTest.cpp +36 -16
  657. data/test/cxx/ServerInstanceDirTest.cpp +1 -1
  658. data/test/cxx/StringMapTest.cpp +61 -0
  659. data/test/cxx/TemplateTest.cpp +118 -0
  660. data/test/cxx/TestSupport.cpp +25 -68
  661. data/test/cxx/TestSupport.h +81 -41
  662. data/test/cxx/{LoggingTest.cpp → UnionStationTest.cpp} +79 -74
  663. data/test/cxx/UtilsTest.cpp +59 -5
  664. data/test/integration_tests/apache2_tests.rb +2 -2
  665. data/test/integration_tests/nginx_tests.rb +1 -1
  666. data/test/integration_tests/spec_helper.rb +7 -5
  667. data/test/oxt/oxt_test_main.cpp +2 -0
  668. data/test/oxt/syscall_interruption_test.cpp +1 -0
  669. data/test/ruby/classic_rails/loader_spec.rb +48 -0
  670. data/test/ruby/classic_rails/preloader_spec.rb +54 -0
  671. data/test/ruby/rack/loader_spec.rb +62 -0
  672. data/test/ruby/rack/preloader_spec.rb +74 -0
  673. data/test/ruby/{abstract_request_handler_spec.rb → request_handler_spec.rb} +31 -68
  674. data/test/ruby/shared/loader_spec.rb +241 -0
  675. data/test/ruby/shared/rails/analytics_logging_extensions_spec.rb +141 -182
  676. data/test/ruby/shared/ruby_loader_spec.rb +55 -0
  677. data/test/ruby/spec_helper.rb +8 -53
  678. data/test/ruby/utils/file_system_watcher_spec.rb +9 -1
  679. data/test/ruby/utils_spec.rb +10 -683
  680. data/test/stub/rack/config.ru +28 -3
  681. data/test/stub/rack/start.rb +47 -0
  682. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/Rakefile +0 -0
  683. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/application_controller.rb +0 -2
  684. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_1.rb +0 -0
  685. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_2.rb +0 -0
  686. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/foo_controller.rb +0 -0
  687. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/helpers/application_helper.rb +0 -0
  688. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/boot.rb +0 -0
  689. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/database.yml +3 -3
  690. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environment.rb +5 -2
  691. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/development.rb +0 -0
  692. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/production.rb +0 -0
  693. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/staging.rb +0 -0
  694. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/inflections.rb +0 -0
  695. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/mime_types.rb +0 -0
  696. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/routes.rb +1 -0
  697. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/about +0 -0
  698. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/console +0 -0
  699. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/dbconsole +0 -0
  700. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/destroy +0 -0
  701. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/generate +0 -0
  702. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/benchmarker +0 -0
  703. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/profiler +0 -0
  704. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/request +0 -0
  705. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/plugin +0 -0
  706. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/inspector +0 -0
  707. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/reaper +0 -0
  708. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/spawner +0 -0
  709. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/runner +0 -0
  710. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/server +0 -0
  711. data/test/stub/{rails_apps/3.0/empty → rails3.0}/Gemfile +0 -0
  712. data/test/stub/rails3.0/Gemfile.lock +80 -0
  713. data/test/stub/{rails_apps/3.0/empty → rails3.0}/Rakefile +0 -0
  714. data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/controllers/application_controller.rb +0 -0
  715. data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/helpers/application_helper.rb +0 -0
  716. data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/views/layouts/application.html.erb +0 -0
  717. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config.ru +0 -0
  718. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/application.rb +0 -0
  719. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/boot.rb +0 -0
  720. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/database.yml +0 -0
  721. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environment.rb +0 -0
  722. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/development.rb +0 -0
  723. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/production.rb +0 -0
  724. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/test.rb +0 -0
  725. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/backtrace_silencers.rb +0 -0
  726. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/inflections.rb +0 -0
  727. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/mime_types.rb +0 -0
  728. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/passenger.rb +0 -0
  729. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/secret_token.rb +0 -0
  730. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/session_store.rb +0 -0
  731. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/locales/en.yml +0 -0
  732. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/routes.rb +0 -0
  733. data/test/stub/{rails_apps/3.0/empty → rails3.0}/db/seeds.rb +0 -0
  734. data/test/stub/{rails_apps/3.0/empty → rails3.0}/doc/README_FOR_APP +0 -0
  735. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/404.html +0 -0
  736. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/422.html +0 -0
  737. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/500.html +0 -0
  738. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/favicon.ico +0 -0
  739. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/index.html +0 -0
  740. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/robots.txt +0 -0
  741. data/test/stub/{rails_apps/3.0/empty → rails3.0}/script/rails +0 -0
  742. data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/performance/browsing_test.rb +0 -0
  743. data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/test_helper.rb +0 -0
  744. data/test/stub/start_error.pl +24 -0
  745. data/test/stub/wsgi/passenger_wsgi.py +71 -3
  746. data/test/support/apache2_controller.rb +2 -2
  747. data/test/support/placebo-preloader.rb +88 -0
  748. data/test/support/test_helper.rb +1 -14
  749. data/test/tut/tut.h +11 -4
  750. metadata +590 -326
  751. data.tar.gz.asc +0 -12
  752. data/PACKAGING.TXT +0 -25
  753. data/build/config.rb +0 -46
  754. data/ext/apache2/HelperAgent.cpp +0 -364
  755. data/ext/boost/call_traits.hpp +0 -24
  756. data/ext/boost/detail/call_traits.hpp +0 -164
  757. data/ext/common/AbstractSpawnManager.h +0 -110
  758. data/ext/common/AgentBase.cpp +0 -432
  759. data/ext/common/ApplicationPool/Client.h +0 -788
  760. data/ext/common/ApplicationPool/Interface.h +0 -295
  761. data/ext/common/ApplicationPool/Pool.h +0 -1327
  762. data/ext/common/ApplicationPool/Server.h +0 -479
  763. data/ext/common/MessageChannel.h +0 -494
  764. data/ext/common/PoolOptions.h +0 -518
  765. data/ext/common/Process.h +0 -253
  766. data/ext/common/Session.h +0 -436
  767. data/ext/common/SpawnManager.h +0 -611
  768. data/ext/google/ChangeLog +0 -167
  769. data/ext/google/dense_hash_map +0 -310
  770. data/ext/google/dense_hash_set +0 -287
  771. data/ext/google/sparse_hash_map +0 -294
  772. data/ext/google/sparse_hash_set +0 -275
  773. data/ext/google/sparsehash/densehashtable.h +0 -1062
  774. data/ext/google/sparsehash/sparseconfig.h +0 -55
  775. data/ext/google/sparsehash/sparsehashtable.h +0 -1015
  776. data/ext/google/sparsetable +0 -1468
  777. data/ext/google/type_traits.h +0 -250
  778. data/ext/nginx/HelperAgent.cpp +0 -1355
  779. data/ext/nginx/ScgiRequestParser.h +0 -375
  780. data/ext/oxt/backtrace.cpp +0 -185
  781. data/ext/oxt/tracable_exception.cpp +0 -89
  782. data/helper-scripts/passenger-spawn-server +0 -106
  783. data/lib/phusion_passenger/abstract_request_handler.rb +0 -766
  784. data/lib/phusion_passenger/abstract_server.rb +0 -372
  785. data/lib/phusion_passenger/abstract_server_collection.rb +0 -335
  786. data/lib/phusion_passenger/app_process.rb +0 -174
  787. data/lib/phusion_passenger/classic_rails/application_spawner.rb +0 -344
  788. data/lib/phusion_passenger/classic_rails/framework_spawner.rb +0 -311
  789. data/lib/phusion_passenger/exceptions.rb +0 -103
  790. data/lib/phusion_passenger/html_template.rb +0 -107
  791. data/lib/phusion_passenger/rack/application_spawner.rb +0 -231
  792. data/lib/phusion_passenger/spawn_manager.rb +0 -359
  793. data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +0 -38
  794. data/lib/phusion_passenger/templates/app_init_error.html.erb +0 -64
  795. data/lib/phusion_passenger/templates/database_error.html.erb +0 -66
  796. data/lib/phusion_passenger/templates/error_layout.html.erb +0 -39
  797. data/lib/phusion_passenger/templates/framework_init_error.html.erb +0 -39
  798. data/lib/phusion_passenger/templates/general_error.html.erb +0 -22
  799. data/lib/phusion_passenger/templates/load_error.html.erb +0 -46
  800. data/lib/phusion_passenger/templates/version_not_found.html.erb +0 -34
  801. data/lib/phusion_passenger/utils/rewindable_input.rb +0 -125
  802. data/lib/phusion_passenger/wsgi/application_spawner.rb +0 -108
  803. data/test/config.yml.example +0 -41
  804. data/test/cxx/ApplicationPool_PoolTest.cpp +0 -33
  805. data/test/cxx/ApplicationPool_PoolTestCases.cpp +0 -1029
  806. data/test/cxx/ApplicationPool_ServerTest.cpp +0 -308
  807. data/test/cxx/ApplicationPool_Server_PoolTest.cpp +0 -80
  808. data/test/cxx/MessageChannelTest.cpp +0 -557
  809. data/test/cxx/PoolOptionsTest.cpp +0 -116
  810. data/test/cxx/SpawnManagerTest.cpp +0 -161
  811. data/test/ruby/abstract_server_collection_spec.rb +0 -247
  812. data/test/ruby/abstract_server_spec.rb +0 -61
  813. data/test/ruby/app_process_spec.rb +0 -43
  814. data/test/ruby/classic_rails/application_spawner_spec.rb +0 -89
  815. data/test/ruby/classic_rails/framework_spawner_spec.rb +0 -92
  816. data/test/ruby/rack/application_spawner_spec.rb +0 -116
  817. data/test/ruby/shared/abstract_server_spec.rb +0 -23
  818. data/test/ruby/shared/spawners/classic_rails/framework_spawner_spec.rb +0 -38
  819. data/test/ruby/shared/spawners/classic_rails/lack_of_rails_gem_version_spec.rb +0 -19
  820. data/test/ruby/shared/spawners/classic_rails/spawner_spec.rb +0 -15
  821. data/test/ruby/shared/spawners/non_preloading_spawner_spec.rb +0 -27
  822. data/test/ruby/shared/spawners/preloading_spawner_spec.rb +0 -29
  823. data/test/ruby/shared/spawners/reload_all_spec.rb +0 -36
  824. data/test/ruby/shared/spawners/reload_single_spec.rb +0 -52
  825. data/test/ruby/shared/spawners/spawn_server_spec.rb +0 -28
  826. data/test/ruby/shared/spawners/spawner_spec.rb +0 -273
  827. data/test/ruby/shared/utils/pseudo_io_spec.rb +0 -60
  828. data/test/ruby/spawn_manager_spec.rb +0 -134
  829. data/test/ruby/wsgi/application_spawner_spec.rb +0 -50
  830. data/test/stub/message_channel.rb +0 -11
  831. data/test/stub/message_channel_2.rb +0 -12
  832. data/test/stub/message_channel_3.rb +0 -19
  833. data/test/stub/rails_apps/3.0/empty/Gemfile.lock +0 -73
  834. data/test/stub/spawn_server.rb +0 -22
  835. metadata.gz.asc +0 -12
@@ -0,0 +1,131 @@
1
+ #include <TestSupport.h>
2
+ #include <ApplicationPool2/Process.h>
3
+ #include <Utils/IOUtils.h>
4
+
5
+ using namespace Passenger;
6
+ using namespace Passenger::ApplicationPool2;
7
+ using namespace std;
8
+
9
+ namespace tut {
10
+ struct ApplicationPool2_ProcessTest {
11
+ BackgroundEventLoop bg;
12
+ SocketListPtr sockets;
13
+ SocketPair adminSocket;
14
+ Pipe errorPipe;
15
+ FileDescriptor server1, server2, server3;
16
+
17
+ ApplicationPool2_ProcessTest() {
18
+ bg.start();
19
+
20
+ struct sockaddr_in addr;
21
+ socklen_t len = sizeof(addr);
22
+ sockets = make_shared<SocketList>();
23
+
24
+ server1 = createTcpServer("127.0.0.1", 0);
25
+ getsockname(server1, (struct sockaddr *) &addr, &len);
26
+ sockets->add("main1",
27
+ "tcp://127.0.0.1:" + toString(addr.sin_port),
28
+ "session", 3);
29
+
30
+ server2 = createTcpServer("127.0.0.1", 0);
31
+ getsockname(server2, (struct sockaddr *) &addr, &len);
32
+ sockets->add("main2",
33
+ "tcp://127.0.0.1:" + toString(addr.sin_port),
34
+ "session", 3);
35
+
36
+ server3 = createTcpServer("127.0.0.1", 0);
37
+ getsockname(server3, (struct sockaddr *) &addr, &len);
38
+ sockets->add("main3",
39
+ "tcp://127.0.0.1:" + toString(addr.sin_port),
40
+ "session", 3);
41
+
42
+ adminSocket = createUnixSocketPair();
43
+ errorPipe = createPipe();
44
+ }
45
+ };
46
+
47
+ DEFINE_TEST_GROUP(ApplicationPool2_ProcessTest);
48
+
49
+ TEST_METHOD(1) {
50
+ // Test initial state.
51
+ ProcessPtr process = make_shared<Process>(bg.safe,
52
+ 123, "", "", adminSocket[0],
53
+ errorPipe[0], sockets, 0, 0);
54
+ ensure_equals(process->utilization(), 0);
55
+ ensure(!process->atFullCapacity());
56
+ }
57
+
58
+ TEST_METHOD(2) {
59
+ // Test opening and closing sessions.
60
+ ProcessPtr process = make_shared<Process>(bg.safe,
61
+ 123, "", "", adminSocket[0],
62
+ errorPipe[0], sockets, 0, 0);
63
+ SessionPtr session = process->newSession();
64
+ SessionPtr session2 = process->newSession();
65
+ ensure_equals(process->sessions, 2);
66
+ process->sessionClosed(session.get());
67
+ ensure_equals(process->sessions, 1);
68
+ process->sessionClosed(session2.get());
69
+ ensure_equals(process->sessions, 0);
70
+ }
71
+
72
+ TEST_METHOD(3) {
73
+ // newSession() checks out the socket with the smallest utilization number
74
+ // and sessionClosed() restores the session utilization statistics.
75
+ ProcessPtr process = make_shared<Process>(bg.safe,
76
+ 123, "", "", adminSocket[0],
77
+ errorPipe[0], sockets, 0, 0);
78
+
79
+ // The first 3 newSession() commands check out an idle socket.
80
+ SessionPtr session1 = process->newSession();
81
+ SessionPtr session2 = process->newSession();
82
+ SessionPtr session3 = process->newSession();
83
+ ensure(session1->getSocket()->name != session2->getSocket()->name);
84
+ ensure(session1->getSocket()->name != session3->getSocket()->name);
85
+ ensure(session2->getSocket()->name != session3->getSocket()->name);
86
+
87
+ // The next 2 newSession() commands check out sockets with sessions == 1.
88
+ SessionPtr session4 = process->newSession();
89
+ SessionPtr session5 = process->newSession();
90
+ ensure(session4->getSocket()->name != session5->getSocket()->name);
91
+
92
+ // There should now be 1 process with 1 session
93
+ // and 2 processes with 2 sessions.
94
+ map<int, int> sessionCount;
95
+ SocketList::const_iterator it;
96
+ for (it = process->sockets->begin(); it != process->sockets->end(); it++) {
97
+ sessionCount[it->sessions]++;
98
+ }
99
+ ensure_equals(sessionCount.size(), 2u);
100
+ ensure_equals(sessionCount[1], 1);
101
+ ensure_equals(sessionCount[2], 2);
102
+
103
+ // Closing the first 3 sessions will result in no processes having 1 session
104
+ // and 1 process having 2 sessions.
105
+ process->sessionClosed(session1.get());
106
+ process->sessionClosed(session2.get());
107
+ process->sessionClosed(session3.get());
108
+ sessionCount.clear();
109
+ for (it = process->sockets->begin(); it != process->sockets->end(); it++) {
110
+ sessionCount[it->sessions]++;
111
+ }
112
+ ensure_equals(sessionCount[0], 1);
113
+ ensure_equals(sessionCount[1], 2);
114
+ }
115
+
116
+ TEST_METHOD(4) {
117
+ // If all sockets are at their full capacity then newSession() will fail.
118
+ ProcessPtr process = make_shared<Process>(bg.safe,
119
+ 123, "", "", adminSocket[0],
120
+ errorPipe[0], sockets, 0, 0);
121
+ vector<SessionPtr> sessions;
122
+ for (int i = 0; i < 9; i++) {
123
+ ensure(!process->atFullCapacity());
124
+ SessionPtr session = process->newSession();
125
+ ensure(session != NULL);
126
+ sessions.push_back(session);
127
+ }
128
+ ensure(process->atFullCapacity());
129
+ ensure(process->newSession() == NULL);
130
+ }
131
+ }
@@ -0,0 +1,229 @@
1
+ #include <TestSupport.h>
2
+ #include <ApplicationPool2/Spawner.h>
3
+ #include <Logging.h>
4
+ #include <Utils/json.h>
5
+ #include <unistd.h>
6
+ #include <climits>
7
+ #include <signal.h>
8
+
9
+ using namespace std;
10
+ using namespace Passenger;
11
+ using namespace Passenger::ApplicationPool2;
12
+
13
+ namespace tut {
14
+ struct ApplicationPool2_SmartSpawnerTest {
15
+ ServerInstanceDirPtr serverInstanceDir;
16
+ ServerInstanceDir::GenerationPtr generation;
17
+ BackgroundEventLoop bg;
18
+
19
+ ApplicationPool2_SmartSpawnerTest() {
20
+ createServerInstanceDirAndGeneration(serverInstanceDir, generation);
21
+ bg.start();
22
+ }
23
+
24
+ ~ApplicationPool2_SmartSpawnerTest() {
25
+ setLogLevel(0);
26
+ unlink("stub/wsgi/passenger_wsgi.pyc");
27
+ }
28
+
29
+ shared_ptr<SmartSpawner> createSpawner(const Options &options, bool exitImmediately = false) {
30
+ char buf[PATH_MAX + 1];
31
+ getcwd(buf, PATH_MAX);
32
+
33
+ vector<string> command;
34
+ command.push_back("ruby");
35
+ command.push_back(string(buf) + "/support/placebo-preloader.rb");
36
+ if (exitImmediately) {
37
+ command.push_back("exit-immediately");
38
+ }
39
+
40
+ return make_shared<SmartSpawner>(bg.safe,
41
+ *resourceLocator,
42
+ generation,
43
+ command,
44
+ options);
45
+ }
46
+
47
+ Options createOptions() {
48
+ Options options;
49
+ options.spawnMethod = "smart";
50
+ options.loadShellEnvvars = false;
51
+ return options;
52
+ }
53
+ };
54
+
55
+ DEFINE_TEST_GROUP_WITH_LIMIT(ApplicationPool2_SmartSpawnerTest, 90);
56
+
57
+ #include "SpawnerTestCases.cpp"
58
+
59
+ TEST_METHOD(80) {
60
+ // If the preloader has crashed then SmartSpawner will
61
+ // restart it and try again.
62
+ Options options = createOptions();
63
+ options.appRoot = "stub/rack";
64
+ options.startCommand = "ruby\1" "start.rb";
65
+ options.startupFile = "stub/rack/start.rb";
66
+ shared_ptr<SmartSpawner> spawner = createSpawner(options);
67
+ spawner->spawn(options);
68
+
69
+ kill(spawner->getPreloaderPid(), SIGTERM);
70
+ // Give it some time to exit.
71
+ usleep(300000);
72
+
73
+ // No exception at next spawn.
74
+ setLogLevel(-1);
75
+ spawner->spawn(options);
76
+ }
77
+
78
+ TEST_METHOD(81) {
79
+ // If the preloader still crashes after the restart then
80
+ // SmartSpawner will throw an exception.
81
+ Options options = createOptions();
82
+ options.appRoot = "stub/rack";
83
+ options.startCommand = "ruby\1" "start.rb";
84
+ options.startupFile = "stub/rack/start.rb";
85
+ setLogLevel(-1);
86
+ shared_ptr<SmartSpawner> spawner = createSpawner(options, true);
87
+ try {
88
+ spawner->spawn(options);
89
+ fail("SpawnException expected");
90
+ } catch (const SpawnException &) {
91
+ // Pass.
92
+ }
93
+ }
94
+
95
+ TEST_METHOD(82) {
96
+ // If the preloader didn't start within the timeout
97
+ // then it's killed and an exception is thrown, with
98
+ // whatever stderr output as error page.
99
+ Options options = createOptions();
100
+ options.appRoot = "stub/rack";
101
+ options.startCommand = "ruby\1" "start.rb";
102
+ options.startupFile = "stub/rack/start.rb";
103
+ options.startTimeout = 300;
104
+
105
+ vector<string> preloaderCommand;
106
+ preloaderCommand.push_back("bash");
107
+ preloaderCommand.push_back("-c");
108
+ preloaderCommand.push_back("echo hello world >&2; sleep 60");
109
+ SmartSpawner spawner(bg.safe,
110
+ *resourceLocator,
111
+ generation,
112
+ preloaderCommand,
113
+ options);
114
+ spawner.forwardStdout = false;
115
+ spawner.forwardStderr = false;
116
+
117
+ try {
118
+ spawner.spawn(options);
119
+ fail("SpawnException expected");
120
+ } catch (const SpawnException &e) {
121
+ ensure_equals(e.getErrorKind(),
122
+ SpawnException::PRELOADER_STARTUP_TIMEOUT);
123
+ ensure_equals(e.getErrorPage(),
124
+ "hello world\n");
125
+ }
126
+ }
127
+
128
+ TEST_METHOD(83) {
129
+ // If the preloader crashed during startup without returning
130
+ // a proper error response, then its stderr output is used
131
+ // as error response instead.
132
+ Options options = createOptions();
133
+ options.appRoot = "stub/rack";
134
+ options.startCommand = "ruby\1" "start.rb";
135
+ options.startupFile = "stub/rack/start.rb";
136
+
137
+ vector<string> preloaderCommand;
138
+ preloaderCommand.push_back("bash");
139
+ preloaderCommand.push_back("-c");
140
+ preloaderCommand.push_back("echo hello world >&2");
141
+ SmartSpawner spawner(bg.safe,
142
+ *resourceLocator,
143
+ generation,
144
+ preloaderCommand,
145
+ options);
146
+ spawner.forwardStdout = false;
147
+ spawner.forwardStderr = false;
148
+
149
+ try {
150
+ spawner.spawn(options);
151
+ fail("SpawnException expected");
152
+ } catch (const SpawnException &e) {
153
+ ensure_equals(e.getErrorKind(),
154
+ SpawnException::PRELOADER_STARTUP_PROTOCOL_ERROR);
155
+ ensure_equals(e.getErrorPage(),
156
+ "hello world\n");
157
+ }
158
+ }
159
+
160
+ TEST_METHOD(84) {
161
+ // If the preloader encountered an error, then the resulting SpawnException
162
+ // takes note of the process's environment variables.
163
+ Options options = createOptions();
164
+ options.appRoot = "stub/rack";
165
+ options.startCommand = "ruby\1" "start.rb";
166
+ options.startupFile = "stub/rack/start.rb";
167
+ options.environmentVariables.push_back(make_pair("PASSENGER_FOO", "foo"));
168
+
169
+ vector<string> preloaderCommand;
170
+ preloaderCommand.push_back("bash");
171
+ preloaderCommand.push_back("-c");
172
+ preloaderCommand.push_back("echo hello world >&2");
173
+ SmartSpawner spawner(bg.safe,
174
+ *resourceLocator,
175
+ generation,
176
+ preloaderCommand,
177
+ options);
178
+ spawner.forwardStdout = false;
179
+ spawner.forwardStderr = false;
180
+
181
+ try {
182
+ spawner.spawn(options);
183
+ fail("SpawnException expected");
184
+ } catch (const SpawnException &e) {
185
+ ensure(containsSubstring(e["envvars"], "PASSENGER_FOO=foo\n"));
186
+ }
187
+ }
188
+
189
+ TEST_METHOD(85) {
190
+ // Test that the spawned process can still write to its stderr
191
+ // after the SmartSpawner has been destroyed.
192
+ DeleteFileEventually d("tmp.output");
193
+ Options options = createOptions();
194
+ options.appRoot = "stub/rack";
195
+
196
+ ProcessPtr process;
197
+ {
198
+ vector<string> preloaderCommand;
199
+ preloaderCommand.push_back("ruby");
200
+ preloaderCommand.push_back(resourceLocator->getHelperScriptsDir() + "/rack-preloader.rb");
201
+ SmartSpawner spawner(bg.safe,
202
+ *resourceLocator,
203
+ generation,
204
+ preloaderCommand,
205
+ options);
206
+ process = spawner.spawn(options);
207
+ }
208
+
209
+ SessionPtr session = process->newSession();
210
+ session->initiate();
211
+
212
+ const char header[] =
213
+ "REQUEST_METHOD\0GET\0"
214
+ "PATH_INFO\0/print_stderr\0";
215
+ string data(header, sizeof(header) - 1);
216
+ data.append("PASSENGER_CONNECT_PASSWORD");
217
+ data.append(1, '\0');
218
+ data.append(process->connectPassword);
219
+ data.append(1, '\0');
220
+
221
+ {
222
+ TemporarilyRedirectStdio redirect("tmp.output");
223
+ writeScalarMessage(session->fd(), data);
224
+ shutdown(session->fd(), SHUT_WR);
225
+ readAll(session->fd());
226
+ }
227
+ ensure_equals(readAll("tmp.output"), "hello world!\n");
228
+ }
229
+ }
@@ -0,0 +1,744 @@
1
+ // Included in DirectSpawnerTest.cpp and SmartSpawnerTest.cpp.
2
+
3
+ #define SETUP_USER_SWITCHING_TEST() \
4
+ if (geteuid() != 0) { \
5
+ return; \
6
+ } \
7
+ TempDirCopy copy("stub/wsgi", "tmp.wsgi"); \
8
+ addUserSwitchingCode(); \
9
+ \
10
+ DeleteFileEventually info1("/tmp/info.txt"); \
11
+ DeleteFileEventually info2("/tmp/info2.txt"); \
12
+ \
13
+ SpawnerPtr spawner; \
14
+ Options options; \
15
+ options = createOptions(); \
16
+ options.appRoot = "tmp.wsgi"; \
17
+ options.appType = "wsgi"; \
18
+ options.defaultUser = testConfig["default_user"].asCString(); \
19
+ options.defaultGroup = testConfig["default_group"].asCString(); \
20
+ spawner = createSpawner(options)
21
+
22
+ #define RUN_USER_SWITCHING_TEST() \
23
+ spawner->spawn(options); \
24
+ BufferedIO io(FileDescriptor(open("/tmp/info.txt", O_RDONLY))); \
25
+ uid_t uid = (uid_t) atol(io.readLine().c_str()); \
26
+ gid_t gid = (gid_t) atol(io.readLine().c_str()); \
27
+ string groups = strip(io.readLine()); \
28
+ /* Avoid compiler warning. */ \
29
+ (void) uid; (void) gid; (void) groups
30
+
31
+ typedef shared_ptr<Spawner> SpawnerPtr;
32
+
33
+ static void addUserSwitchingCode() {
34
+ FILE *f = fopen("tmp.wsgi/passenger_wsgi.py", "a");
35
+ fputs(
36
+ "\n"
37
+ "import os\n"
38
+ "f = open('/tmp/info.txt', 'w')\n"
39
+ "f.write(str(os.getuid()) + '\\n')\n"
40
+ "f.write(str(os.getgid()) + '\\n')\n"
41
+ "f.write(os.popen('groups').read() + '\\n')\n"
42
+ "f.close()\n",
43
+ f);
44
+ fclose(f);
45
+
46
+ rename("tmp.wsgi/passenger_wsgi.py", "tmp.wsgi/passenger_wsgi.py.real");
47
+ symlink("passenger_wsgi.py.real", "tmp.wsgi/passenger_wsgi.py");
48
+ }
49
+
50
+ static void checkin(ProcessPtr process, Connection *conn) {
51
+ process->sockets->front().checkinConnection(*conn);
52
+ }
53
+
54
+ static string userNameForUid(uid_t uid) {
55
+ return getpwuid(uid)->pw_name;
56
+ }
57
+
58
+ static string groupNameForGid(gid_t gid) {
59
+ return getgrgid(gid)->gr_name;
60
+ }
61
+
62
+ static uid_t uidFor(const string &userName) {
63
+ return getpwnam(userName.c_str())->pw_uid;
64
+ }
65
+
66
+ static gid_t gidFor(const string &groupName) {
67
+ return getgrnam(groupName.c_str())->gr_gid;
68
+ }
69
+
70
+ static string primaryGroupFor(const string &userName) {
71
+ gid_t gid = getpwnam(userName.c_str())->pw_gid;
72
+ return getgrgid(gid)->gr_name;
73
+ }
74
+
75
+ static string strip(const string &str) {
76
+ if (!str.empty() && str[str.size() - 1] == '\n') {
77
+ string result = str;
78
+ result.erase(str.size() - 1, 1);
79
+ return result;
80
+ } else {
81
+ return str;
82
+ }
83
+ }
84
+
85
+ struct TemporarilyRedirectStdio {
86
+ FileDescriptor oldStdout, oldStderr, newStdio;
87
+
88
+ TemporarilyRedirectStdio(const string &filename) {
89
+ oldStdout = FileDescriptor(dup(STDOUT_FILENO));
90
+ oldStderr = FileDescriptor(dup(STDERR_FILENO));
91
+ newStdio = FileDescriptor(open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0600));
92
+ if (oldStdout == -1 || oldStderr == -1 || newStdio == -1) {
93
+ throw RuntimeException("Cannot dup or open file descriptor");
94
+ }
95
+ dup2(newStdio, STDOUT_FILENO);
96
+ dup2(newStdio, STDERR_FILENO);
97
+ }
98
+
99
+ ~TemporarilyRedirectStdio() {
100
+ dup2(oldStdout, STDOUT_FILENO);
101
+ dup2(oldStderr, STDERR_FILENO);
102
+ }
103
+ };
104
+
105
+ TEST_METHOD(1) {
106
+ // Basic spawning test.
107
+ Options options = createOptions();
108
+ options.appRoot = "stub/rack";
109
+ options.startCommand = "ruby\1" "start.rb";
110
+ options.startupFile = "start.rb";
111
+ SpawnerPtr spawner = createSpawner(options);
112
+ ProcessPtr process = spawner->spawn(options);
113
+ ensure_equals(process->sockets->size(), 1u);
114
+
115
+ Connection conn = process->sockets->front().checkoutConnection();
116
+ ScopeGuard guard(boost::bind(checkin, process, &conn));
117
+ writeExact(conn.fd, "ping\n");
118
+ ensure_equals(readAll(conn.fd), "pong\n");
119
+ }
120
+
121
+ TEST_METHOD(2) {
122
+ // It enforces the given start timeout.
123
+ Options options = createOptions();
124
+ options.appRoot = "stub";
125
+ options.startCommand = "sleep\1" "60";
126
+ options.startupFile = ".";
127
+ options.startTimeout = 300;
128
+ SpawnerPtr spawner = createSpawner(options);
129
+ try {
130
+ spawner->spawn(options);
131
+ fail("Timeout expected");
132
+ } catch (const SpawnException &e) {
133
+ ensure_equals(e.getErrorKind(),
134
+ SpawnException::APP_STARTUP_TIMEOUT);
135
+ }
136
+ }
137
+
138
+ TEST_METHOD(3) {
139
+ // Any protocol errors during startup are caught and result
140
+ // in exceptions.
141
+ Options options = createOptions();
142
+ options.appRoot = "stub";
143
+ options.startCommand = "echo\1" "!> hello world";
144
+ options.startupFile = ".";
145
+ SpawnerPtr spawner = createSpawner(options);
146
+ try {
147
+ spawner->spawn(options);
148
+ fail("Exception expected");
149
+ } catch (const SpawnException &e) {
150
+ ensure_equals(e.getErrorKind(),
151
+ SpawnException::APP_STARTUP_PROTOCOL_ERROR);
152
+ }
153
+ }
154
+
155
+ TEST_METHOD(4) {
156
+ // The application may respond with a special Error response,
157
+ // which will result in a SpawnException with the content.
158
+ Options options = createOptions();
159
+ options.appRoot = "stub";
160
+ options.startCommand = "perl\1" "start_error.pl";
161
+ options.startupFile = "start_error.pl";
162
+ SpawnerPtr spawner = createSpawner(options);
163
+ try {
164
+ spawner->spawn(options);
165
+ fail("SpawnException expected");
166
+ } catch (const SpawnException &e) {
167
+ ensure_equals(e.getErrorKind(),
168
+ SpawnException::APP_STARTUP_EXPLAINABLE_ERROR);
169
+ ensure_equals(e.getErrorPage(),
170
+ "He's dead, Jim!\n"
171
+ "Relax, I'm a doctor.\n");
172
+ }
173
+ }
174
+
175
+ TEST_METHOD(5) {
176
+ // The start timeout is enforced even while reading the error
177
+ // response.
178
+ Options options = createOptions();
179
+ options.appRoot = "stub";
180
+ options.startCommand = "perl\1" "start_error.pl\1" "freeze";
181
+ options.startupFile = "start_error.pl";
182
+ options.startTimeout = 300;
183
+ SpawnerPtr spawner = createSpawner(options);
184
+ try {
185
+ spawner->spawn(options);
186
+ fail("Timeout expected");
187
+ } catch (const SpawnException &e) {
188
+ ensure_equals(e.getErrorKind(),
189
+ SpawnException::APP_STARTUP_TIMEOUT);
190
+ }
191
+ }
192
+
193
+ TEST_METHOD(6) {
194
+ // The reported PID is correct.
195
+ Options options = createOptions();
196
+ options.appRoot = "stub/rack";
197
+ options.startCommand = "ruby\1" "start.rb";
198
+ options.startupFile = "start.rb";
199
+ SpawnerPtr spawner = createSpawner(options);
200
+ ProcessPtr process = spawner->spawn(options);
201
+ ensure_equals(process->sockets->size(), 1u);
202
+
203
+ Connection conn = process->sockets->front().checkoutConnection();
204
+ ScopeGuard guard(boost::bind(checkin, process, &conn));
205
+ writeExact(conn.fd, "pid\n");
206
+ ensure_equals(readAll(conn.fd), toString(process->pid) + "\n");
207
+ }
208
+
209
+ TEST_METHOD(7) {
210
+ // Custom environment variables can be passed.
211
+ Options options = createOptions();
212
+ options.appRoot = "stub/rack";
213
+ options.startCommand = "ruby\1" "start.rb";
214
+ options.startupFile = "start.rb";
215
+ options.environmentVariables.push_back(make_pair("PASSENGER_FOO", "foo"));
216
+ options.environmentVariables.push_back(make_pair("PASSENGER_BAR", "bar"));
217
+ SpawnerPtr spawner = createSpawner(options);
218
+ ProcessPtr process = spawner->spawn(options);
219
+ ensure_equals(process->sockets->size(), 1u);
220
+
221
+ Connection conn = process->sockets->front().checkoutConnection();
222
+ ScopeGuard guard(boost::bind(checkin, process, &conn));
223
+ writeExact(conn.fd, "envvars\n");
224
+ string envvars = readAll(conn.fd);
225
+ ensure("(1)", envvars.find("PASSENGER_FOO = foo\n") != string::npos);
226
+ ensure("(2)", envvars.find("PASSENGER_BAR = bar\n") != string::npos);
227
+ }
228
+
229
+ TEST_METHOD(8) {
230
+ // Any raised SpawnExceptions take note of the process's environment variables.
231
+ Options options = createOptions();
232
+ options.appRoot = "stub";
233
+ options.startCommand = "echo\1" "!> hello world";
234
+ options.startupFile = ".";
235
+ options.environmentVariables.push_back(make_pair("PASSENGER_FOO", "foo"));
236
+ SpawnerPtr spawner = createSpawner(options);
237
+ try {
238
+ spawner->spawn(options);
239
+ fail("Exception expected");
240
+ } catch (const SpawnException &e) {
241
+ ensure(containsSubstring(e["envvars"], "PASSENGER_FOO=foo\n"));
242
+ }
243
+ }
244
+
245
+ TEST_METHOD(9) {
246
+ // It raises an exception if the user does not have a access to one
247
+ // of the app root's parent directories, or the app root itself.
248
+ runShellCommand("mkdir -p tmp.check/a/b/c");
249
+ TempDirCopy dir("stub/rack", "tmp.check/a/b/c/d");
250
+ TempDir dir2("tmp.check");
251
+
252
+ char buffer[PATH_MAX];
253
+ string cwd = getcwd(buffer, sizeof(buffer));
254
+
255
+ Options options = createOptions();
256
+ options.appRoot = "tmp.check/a/b/c/d";
257
+ options.appType = "rack";
258
+ SpawnerPtr spawner = createSpawner(options);
259
+
260
+ if (getuid() != 0) {
261
+ // TODO: implement this test for root too
262
+ runShellCommand("chmod 000 tmp.check/a/b/c/d");
263
+ runShellCommand("chmod 600 tmp.check/a/b/c");
264
+ runShellCommand("chmod 600 tmp.check/a");
265
+
266
+ try {
267
+ spawner->spawn(options);
268
+ fail("SpawnException expected");
269
+ } catch (const SpawnException &e) {
270
+ ensure("(1)", containsSubstring(e.getErrorPage(),
271
+ "the parent directory '" + cwd + "/tmp.check/a' has wrong permissions"));
272
+ }
273
+
274
+ runShellCommand("chmod 700 tmp.check/a");
275
+ try {
276
+ spawner->spawn(options);
277
+ fail("SpawnException expected");
278
+ } catch (const SpawnException &e) {
279
+ ensure("(2)", containsSubstring(e.getErrorPage(),
280
+ "the parent directory '" + cwd + "/tmp.check/a/b/c' has wrong permissions"));
281
+ }
282
+
283
+ runShellCommand("chmod 700 tmp.check/a/b/c");
284
+ try {
285
+ spawner->spawn(options);
286
+ fail("SpawnException expected");
287
+ } catch (const SpawnException &e) {
288
+ ensure("(3)", containsSubstring(e.getErrorPage(),
289
+ "However this directory is not accessible because it has wrong permissions."));
290
+ }
291
+
292
+ runShellCommand("chmod 700 tmp.check/a/b/c/d");
293
+ spawner->spawn(options); // Should not throw.
294
+ }
295
+ }
296
+
297
+ TEST_METHOD(10) {
298
+ // It forwards all stdout and stderr output, even after the corresponding
299
+ // Process object has been destroyed.
300
+ DeleteFileEventually d("tmp.output");
301
+ Options options = createOptions();
302
+ options.appRoot = "stub/rack";
303
+ options.appType = "rack";
304
+ SpawnerPtr spawner = createSpawner(options);
305
+ ProcessPtr process = spawner->spawn(options);
306
+
307
+ SessionPtr session = process->newSession();
308
+ session->initiate();
309
+
310
+ const char header[] =
311
+ "REQUEST_METHOD\0GET\0"
312
+ "PATH_INFO\0/print_stdout_and_stderr\0";
313
+ string data(header, sizeof(header) - 1);
314
+ data.append("PASSENGER_CONNECT_PASSWORD");
315
+ data.append(1, '\0');
316
+ data.append(process->connectPassword);
317
+ data.append(1, '\0');
318
+
319
+ {
320
+ TemporarilyRedirectStdio redirect("tmp.output");
321
+ writeScalarMessage(session->fd(), data);
322
+ shutdown(session->fd(), SHUT_WR);
323
+ readAll(session->fd());
324
+ usleep(20000); // Give the I/O event loop some time to handle the data.
325
+ }
326
+ ensure_equals(readAll("tmp.output"), "hello stdout!\nhello stderr!\n");
327
+ }
328
+
329
+ // It raises an exception if getStartupCommand() is empty.
330
+
331
+ /******* User switching tests *******/
332
+
333
+ // If 'user' is set
334
+ // and 'user' is 'root'
335
+ TEST_METHOD(20) {
336
+ // It changes the user to the value of 'defaultUser'.
337
+ SETUP_USER_SWITCHING_TEST();
338
+ options.user = "root";
339
+ RUN_USER_SWITCHING_TEST();
340
+ ensure_equals(userNameForUid(uid), testConfig["default_user"]);
341
+ }
342
+
343
+ TEST_METHOD(21) {
344
+ // If 'group' is given, it changes group to the given group name.
345
+ SETUP_USER_SWITCHING_TEST();
346
+ options.user = "root";
347
+ options.group = testConfig["normal_group_1"].asCString();
348
+ RUN_USER_SWITCHING_TEST();
349
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_1"]);
350
+ }
351
+
352
+ TEST_METHOD(22) {
353
+ // If 'group' is set to the root group, it changes group to defaultGroup.
354
+ SETUP_USER_SWITCHING_TEST();
355
+ string rootGroup = groupNameForGid(0);
356
+ options.user = "root";
357
+ options.group = rootGroup.c_str();
358
+ RUN_USER_SWITCHING_TEST();
359
+ ensure_equals(groupNameForGid(gid), testConfig["default_group"]);
360
+ }
361
+
362
+ // and 'group' is set to '!STARTUP_FILE!'"
363
+ TEST_METHOD(23) {
364
+ // It changes the group to the startup file's group.
365
+ SETUP_USER_SWITCHING_TEST();
366
+ string rootGroup = groupNameForGid(0);
367
+ options.user = "root";
368
+ options.group = "!STARTUP_FILE!";
369
+ lchown("tmp.wsgi/passenger_wsgi.py",
370
+ (uid_t) -1,
371
+ gidFor(testConfig["normal_group_1"].asString()));
372
+ RUN_USER_SWITCHING_TEST();
373
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_1"]);
374
+ }
375
+
376
+ TEST_METHOD(24) {
377
+ // If the startup file is a symlink, then it uses the symlink's group, not the target's group
378
+ SETUP_USER_SWITCHING_TEST();
379
+ string rootGroup = groupNameForGid(0);
380
+ options.user = "root";
381
+ options.group = "!STARTUP_FILE!";
382
+ lchown("tmp.wsgi/passenger_wsgi.py",
383
+ (uid_t) -1,
384
+ gidFor(testConfig["normal_group_2"].asString()));
385
+ chown("tmp.wsgi/passenger_wsgi.py.real",
386
+ (uid_t) -1,
387
+ gidFor(testConfig["normal_group_1"].asString()));
388
+ RUN_USER_SWITCHING_TEST();
389
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_2"]);
390
+ }
391
+
392
+ TEST_METHOD(25) {
393
+ // If 'group' is not given, it changes the group to defaultUser's primary group.
394
+ SETUP_USER_SWITCHING_TEST();
395
+ options.user = "root";
396
+ RUN_USER_SWITCHING_TEST();
397
+ ensure_equals(groupNameForGid(gid),
398
+ primaryGroupFor(testConfig["default_user"].asString()));
399
+ }
400
+
401
+ // and 'user' is not 'root'
402
+ TEST_METHOD(29) {
403
+ // It changes the user to the given username.
404
+ SETUP_USER_SWITCHING_TEST();
405
+ options.user = testConfig["normal_user_1"].asCString();
406
+ RUN_USER_SWITCHING_TEST();
407
+ ensure_equals(userNameForUid(uid), testConfig["normal_user_1"]);
408
+ }
409
+
410
+ TEST_METHOD(30) {
411
+ // If 'group' is given, it changes group to the given group name.
412
+ // It changes the user to the given username.
413
+ SETUP_USER_SWITCHING_TEST();
414
+ options.user = testConfig["normal_user_1"].asCString();
415
+ options.group = testConfig["normal_group_1"].asCString();
416
+ RUN_USER_SWITCHING_TEST();
417
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_1"].asString());
418
+ }
419
+
420
+ TEST_METHOD(31) {
421
+ // If 'group' is set to the root group, it changes group to defaultGroup.
422
+ // It changes the user to the given username.
423
+ SETUP_USER_SWITCHING_TEST();
424
+ string rootGroup = groupNameForGid(0);
425
+ options.user = testConfig["normal_user_1"].asCString();
426
+ options.group = rootGroup.c_str();
427
+ RUN_USER_SWITCHING_TEST();
428
+ ensure_equals(groupNameForGid(gid), testConfig["default_group"].asString());
429
+ }
430
+
431
+ // and 'group' is set to '!STARTUP_FILE!'
432
+ TEST_METHOD(32) {
433
+ // It changes the group to the startup file's group.
434
+ SETUP_USER_SWITCHING_TEST();
435
+ options.user = testConfig["normal_user_1"].asCString();
436
+ options.group = "!STARTUP_FILE!";
437
+ lchown("tmp.wsgi/passenger_wsgi.py",
438
+ (uid_t) -1,
439
+ gidFor(testConfig["normal_group_1"].asString()));
440
+ RUN_USER_SWITCHING_TEST();
441
+ ensure_equals(groupNameForGid(gid),
442
+ testConfig["normal_group_1"].asString());
443
+ }
444
+
445
+ TEST_METHOD(33) {
446
+ // If the startup file is a symlink, then it uses the
447
+ // symlink's group, not the target's group.
448
+ SETUP_USER_SWITCHING_TEST();
449
+ options.user = testConfig["normal_user_1"].asCString();
450
+ options.group = "!STARTUP_FILE!";
451
+ lchown("tmp.wsgi/passenger_wsgi.py",
452
+ (uid_t) -1,
453
+ gidFor(testConfig["normal_group_2"].asString()));
454
+ chown("tmp.wsgi/passenger_wsgi.py.real",
455
+ (uid_t) -1,
456
+ gidFor(testConfig["normal_group_1"].asString()));
457
+ RUN_USER_SWITCHING_TEST();
458
+ ensure_equals(groupNameForGid(gid),
459
+ testConfig["normal_group_2"].asString());
460
+ }
461
+
462
+ TEST_METHOD(34) {
463
+ // If 'group' is not given, it changes the group to the user's primary group.
464
+ SETUP_USER_SWITCHING_TEST();
465
+ options.user = testConfig["normal_user_1"].asCString();
466
+ RUN_USER_SWITCHING_TEST();
467
+ ensure_equals(groupNameForGid(gid),
468
+ primaryGroupFor(testConfig["normal_user_1"].asString()));
469
+ }
470
+
471
+ // and the given username does not exist
472
+ TEST_METHOD(38) {
473
+ // It changes the user to the value of defaultUser.
474
+ SETUP_USER_SWITCHING_TEST();
475
+ options.user = testConfig["nonexistant_user"].asCString();
476
+ RUN_USER_SWITCHING_TEST();
477
+ ensure_equals(userNameForUid(uid), testConfig["default_user"].asString());
478
+ }
479
+
480
+ TEST_METHOD(39) {
481
+ // If 'group' is given, it changes group to the given group name.
482
+ SETUP_USER_SWITCHING_TEST();
483
+ options.user = testConfig["nonexistant_user"].asCString();
484
+ options.group = testConfig["normal_group_1"].asCString();
485
+ RUN_USER_SWITCHING_TEST();
486
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_1"].asString());
487
+ }
488
+
489
+ TEST_METHOD(40) {
490
+ // If 'group' is set to the root group, it changes group to defaultGroup.
491
+ SETUP_USER_SWITCHING_TEST();
492
+ string rootGroup = groupNameForGid(0);
493
+ options.user = testConfig["nonexistant_user"].asCString();
494
+ options.group = rootGroup;
495
+ RUN_USER_SWITCHING_TEST();
496
+ ensure_equals(groupNameForGid(gid), testConfig["default_group"].asString());
497
+ }
498
+
499
+ // and 'group' is set to '!STARTUP_FILE!'
500
+ TEST_METHOD(41) {
501
+ // It changes the group to the startup file's group.
502
+ SETUP_USER_SWITCHING_TEST();
503
+ options.user = testConfig["nonexistant_user"].asCString();
504
+ options.group = "!STARTUP_FILE!";
505
+ lchown("tmp.wsgi/passenger_wsgi.py",
506
+ (uid_t) -1,
507
+ gidFor(testConfig["normal_group_1"].asString()));
508
+ RUN_USER_SWITCHING_TEST();
509
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_1"].asString());
510
+ }
511
+
512
+ TEST_METHOD(42) {
513
+ // If the startup file is a symlink, then it uses the
514
+ // symlink's group, not the target's group.
515
+ SETUP_USER_SWITCHING_TEST();
516
+ options.user = testConfig["nonexistant_user"].asCString();
517
+ options.group = "!STARTUP_FILE!";
518
+ lchown("tmp.wsgi/passenger_wsgi.py",
519
+ (uid_t) -1,
520
+ gidFor(testConfig["normal_group_2"].asString()));
521
+ chown("tmp.wsgi/passenger_wsgi.py.real",
522
+ (uid_t) -1,
523
+ gidFor(testConfig["normal_group_1"].asString()));
524
+ RUN_USER_SWITCHING_TEST();
525
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_2"].asString());
526
+ }
527
+
528
+ TEST_METHOD(43) {
529
+ // If 'group' is not given, it changes the group to defaultUser's primary group.
530
+ SETUP_USER_SWITCHING_TEST();
531
+ options.user = testConfig["nonexistant_user"].asCString();
532
+ RUN_USER_SWITCHING_TEST();
533
+ ensure_equals(groupNameForGid(gid),
534
+ primaryGroupFor(testConfig["default_user"].asString()));
535
+ }
536
+
537
+ // If 'user' is not set
538
+ // and the startup file's owner exists
539
+ TEST_METHOD(47) {
540
+ // It changes the user to the owner of the startup file.
541
+ SETUP_USER_SWITCHING_TEST();
542
+ lchown("tmp.wsgi/passenger_wsgi.py",
543
+ uidFor(testConfig["normal_user_1"].asString()),
544
+ (gid_t) -1);
545
+ RUN_USER_SWITCHING_TEST();
546
+ ensure_equals(userNameForUid(uid), testConfig["normal_user_1"].asString());
547
+ }
548
+
549
+ TEST_METHOD(48) {
550
+ // If the startup file is a symlink, then it uses the symlink's owner, not the target's owner.
551
+ SETUP_USER_SWITCHING_TEST();
552
+ lchown("tmp.wsgi/passenger_wsgi.py",
553
+ uidFor(testConfig["normal_user_2"].asString()),
554
+ (gid_t) -1);
555
+ chown("tmp.wsgi/passenger_wsgi.py.real",
556
+ uidFor(testConfig["normal_user_1"].asString()),
557
+ (gid_t) -1);
558
+ RUN_USER_SWITCHING_TEST();
559
+ ensure_equals(userNameForUid(uid), testConfig["normal_user_2"].asString());
560
+ }
561
+
562
+ TEST_METHOD(49) {
563
+ // If 'group' is given, it changes group to the given group name.
564
+ SETUP_USER_SWITCHING_TEST();
565
+ lchown("tmp.wsgi/passenger_wsgi.py",
566
+ uidFor(testConfig["normal_user_1"].asString()),
567
+ (gid_t) -1);
568
+ options.group = testConfig["normal_group_1"].asCString();
569
+ RUN_USER_SWITCHING_TEST();
570
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_1"].asString());
571
+ }
572
+
573
+ TEST_METHOD(50) {
574
+ // If 'group' is set to the root group, it changes group to defaultGroup.
575
+ SETUP_USER_SWITCHING_TEST();
576
+ lchown("tmp.wsgi/passenger_wsgi.py",
577
+ uidFor(testConfig["normal_user_1"].asString()),
578
+ (gid_t) -1);
579
+ string rootGroup = groupNameForGid(0);
580
+ options.group = rootGroup;
581
+ RUN_USER_SWITCHING_TEST();
582
+ ensure_equals(groupNameForGid(gid), testConfig["default_group"].asString());
583
+ }
584
+
585
+ // and 'group' is set to '!STARTUP_FILE!'
586
+ TEST_METHOD(51) {
587
+ // It changes the group to the startup file's group.
588
+ SETUP_USER_SWITCHING_TEST();
589
+ options.group = "!STARTUP_FILE!";
590
+ lchown("tmp.wsgi/passenger_wsgi.py",
591
+ (uid_t) -1,
592
+ gidFor(testConfig["normal_group_1"].asString()));
593
+ RUN_USER_SWITCHING_TEST();
594
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_1"].asString());
595
+ }
596
+
597
+ TEST_METHOD(52) {
598
+ // If the startup file is a symlink, then it uses the symlink's
599
+ // group, not the target's group.
600
+ SETUP_USER_SWITCHING_TEST();
601
+ options.group = "!STARTUP_FILE!";
602
+ lchown("tmp.wsgi/passenger_wsgi.py",
603
+ (uid_t) -1,
604
+ gidFor(testConfig["normal_group_2"].asString()));
605
+ chown("tmp.wsgi/passenger_wsgi.py.real",
606
+ (uid_t) -1,
607
+ gidFor(testConfig["normal_group_1"].asString()));
608
+ RUN_USER_SWITCHING_TEST();
609
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_2"].asString());
610
+ }
611
+
612
+ TEST_METHOD(53) {
613
+ // If 'group' is not given, it changes the group to the startup file's owner's primary group.
614
+ SETUP_USER_SWITCHING_TEST();
615
+ lchown("tmp.wsgi/passenger_wsgi.py",
616
+ uidFor(testConfig["normal_user_1"].asString()),
617
+ (gid_t) -1);
618
+ RUN_USER_SWITCHING_TEST();
619
+ ensure_equals(groupNameForGid(gid),
620
+ primaryGroupFor(testConfig["normal_user_1"].asString()));
621
+ }
622
+
623
+ // and the startup file's owner doesn't exist
624
+ TEST_METHOD(57) {
625
+ // It changes the user to the value of defaultUser.
626
+ SETUP_USER_SWITCHING_TEST();
627
+ lchown("tmp.wsgi/passenger_wsgi.py",
628
+ (uid_t) testConfig["nonexistant_uid"].asInt64(),
629
+ (gid_t) -1);
630
+ RUN_USER_SWITCHING_TEST();
631
+ ensure_equals(userNameForUid(uid), testConfig["default_user"].asString());
632
+ }
633
+
634
+ TEST_METHOD(58) {
635
+ // If 'group' is given, it changes group to the given group name.
636
+ SETUP_USER_SWITCHING_TEST();
637
+ lchown("tmp.wsgi/passenger_wsgi.py",
638
+ (uid_t) testConfig["nonexistant_uid"].asInt64(),
639
+ (gid_t) -1);
640
+ options.group = testConfig["normal_group_1"].asCString();
641
+ RUN_USER_SWITCHING_TEST();
642
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_1"].asString());
643
+ }
644
+
645
+ TEST_METHOD(59) {
646
+ // If 'group' is set to the root group, it changes group to defaultGroup.
647
+ SETUP_USER_SWITCHING_TEST();
648
+ lchown("tmp.wsgi/passenger_wsgi.py",
649
+ (uid_t) testConfig["nonexistant_uid"].asInt64(),
650
+ (gid_t) -1);
651
+ string rootGroup = groupNameForGid(0);
652
+ options.group = rootGroup;
653
+ RUN_USER_SWITCHING_TEST();
654
+ ensure_equals(groupNameForGid(gid), testConfig["default_group"].asString());
655
+ }
656
+
657
+ // and 'group' is set to '!STARTUP_FILE!'
658
+ // and the startup file's group doesn't exist
659
+ TEST_METHOD(60) {
660
+ // It changes the group to the value given by defaultGroup.
661
+ SETUP_USER_SWITCHING_TEST();
662
+ lchown("tmp.wsgi/passenger_wsgi.py",
663
+ (uid_t) testConfig["nonexistant_uid"].asInt64(),
664
+ (gid_t) testConfig["nonexistant_gid"].asInt64());
665
+ options.group = "!STARTUP_FILE!";
666
+ RUN_USER_SWITCHING_TEST();
667
+ ensure_equals(groupNameForGid(gid), testConfig["default_group"].asString());
668
+ }
669
+
670
+ // and the startup file's group exists
671
+ TEST_METHOD(61) {
672
+ // It changes the group to the startup file's group.
673
+ SETUP_USER_SWITCHING_TEST();
674
+ lchown("tmp.wsgi/passenger_wsgi.py",
675
+ (uid_t) testConfig["nonexistant_uid"].asInt64(),
676
+ gidFor(testConfig["normal_group_1"].asString()));
677
+ options.group = "!STARTUP_FILE!";
678
+ RUN_USER_SWITCHING_TEST();
679
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_1"].asString());
680
+ }
681
+
682
+ TEST_METHOD(62) {
683
+ // If the startup file is a symlink, then it uses the symlink's group, not the target's group.
684
+ SETUP_USER_SWITCHING_TEST();
685
+ lchown("tmp.wsgi/passenger_wsgi.py",
686
+ (uid_t) testConfig["nonexistant_uid"].asInt64(),
687
+ gidFor(testConfig["normal_group_2"].asString()));
688
+ chown("tmp.wsgi/passenger_wsgi.py.real",
689
+ (uid_t) -1,
690
+ gidFor(testConfig["normal_group_1"].asString()));
691
+ options.group = "!STARTUP_FILE!";
692
+ RUN_USER_SWITCHING_TEST();
693
+ ensure_equals(groupNameForGid(gid), testConfig["normal_group_2"].asString());
694
+ }
695
+
696
+ TEST_METHOD(63) {
697
+ // If 'group' is not given, it changes the group to defaultUser's primary group.
698
+ SETUP_USER_SWITCHING_TEST();
699
+ lchown("tmp.wsgi/passenger_wsgi.py",
700
+ (uid_t) testConfig["nonexistant_uid"].asInt64(),
701
+ (gid_t) -1);
702
+ RUN_USER_SWITCHING_TEST();
703
+ ensure_equals(groupNameForGid(gid), primaryGroupFor(testConfig["default_user"].asString()));
704
+ }
705
+
706
+ TEST_METHOD(67) {
707
+ // It raises an error if it tries to lower to 'defaultUser',
708
+ // but that user doesn't exist.
709
+ SETUP_USER_SWITCHING_TEST();
710
+ options.user = "root";
711
+ options.defaultUser = testConfig["nonexistant_user"].asCString();
712
+ try {
713
+ RUN_USER_SWITCHING_TEST();
714
+ fail();
715
+ } catch (const RuntimeException &e) {
716
+ ensure(containsSubstring(e.what(), "Cannot determine a user to lower privilege to"));
717
+ }
718
+ }
719
+
720
+ TEST_METHOD(68) {
721
+ // It raises an error if it tries to lower to 'default_group',
722
+ // but that group doesn't exist.
723
+ SETUP_USER_SWITCHING_TEST();
724
+ options.user = testConfig["normal_user_1"].asCString();
725
+ options.group = groupNameForGid(0);
726
+ options.defaultGroup = testConfig["nonexistant_group"].asCString();
727
+ try {
728
+ RUN_USER_SWITCHING_TEST();
729
+ fail();
730
+ } catch (const RuntimeException &e) {
731
+ ensure(containsSubstring(e.what(), "Cannot determine a group to lower privilege to"));
732
+ }
733
+ }
734
+
735
+ TEST_METHOD(69) {
736
+ // Changes supplementary groups to the owner's default supplementary groups.
737
+ SETUP_USER_SWITCHING_TEST();
738
+ options.user = testConfig["normal_user_1"].asCString();
739
+ RUN_USER_SWITCHING_TEST();
740
+ runShellCommand(("groups " + testConfig["normal_user_1"].asString() + " > /tmp/info2.txt").c_str());
741
+ string defaultGroups = strip(readAll("/tmp/info2.txt"));
742
+ // default_groups.gsub!(/.*: */, '')
743
+ ensure_equals(groups, defaultGroups);
744
+ }