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
@@ -40,14 +40,14 @@ namespace tut {
40
40
  TempDir d("test.tmp");
41
41
  touchFile("test.tmp/test.txt");
42
42
 
43
- system("chmod a= test.tmp");
43
+ runShellCommand("chmod a= test.tmp");
44
44
  ensure(!checker.changed("test.tmp/test.txt"));
45
45
 
46
46
  // Should still be false.
47
47
  ensure(!checker.changed("test.tmp/test.txt"));
48
48
 
49
49
  // Now make it accessible again...
50
- system("chmod u=rwx test.tmp");
50
+ runShellCommand("chmod u=rwx test.tmp");
51
51
  ensure(checker.changed("test.tmp/test.txt"));
52
52
  }
53
53
  }
@@ -90,20 +90,20 @@ namespace tut {
90
90
  }
91
91
 
92
92
  TEST_METHOD(6) {
93
- // File is changed if existed but has now been deleted.
93
+ // File is not changed if existed and has now been deleted.
94
94
  FileChangeChecker checker(10);
95
95
 
96
96
  touchFile("test.txt");
97
97
  checker.changed("test.txt");
98
98
  unlink("test.txt");
99
- ensure("test.txt is considered changed if it has been deleted",
100
- checker.changed("test.txt"));
99
+ ensure("test.txt is not considered changed if it has been deleted",
100
+ !checker.changed("test.txt"));
101
101
 
102
102
  touchFile("test2.txt");
103
103
  checker.changed("test2.txt");
104
104
  unlink("test2.txt");
105
- ensure("test2.txt is considered changed if it has been deleted",
106
- checker.changed("test2.txt"));
105
+ ensure("test2.txt is not considered changed if it has been deleted",
106
+ !checker.changed("test2.txt"));
107
107
  }
108
108
 
109
109
  TEST_METHOD(7) {
@@ -138,11 +138,11 @@ namespace tut {
138
138
  checker.changed("test.tmp/test.txt");
139
139
 
140
140
  touchFile("test.tmp/test.txt", 2);
141
- system("chmod a= test.tmp");
141
+ runShellCommand("chmod a= test.tmp");
142
142
  ensure("First check returns false", !checker.changed("test.tmp/test.txt"));
143
143
 
144
144
  // Now make it accessible again...
145
- system("chmod u=rwx test.tmp");
145
+ runShellCommand("chmod u=rwx test.tmp");
146
146
  ensure("Second check returns true", checker.changed("test.tmp/test.txt"));
147
147
  }
148
148
  }
@@ -201,14 +201,14 @@ namespace tut {
201
201
 
202
202
  FileChangeChecker checker(10);
203
203
  TempDir d("test.tmp");
204
- touchFile("test.tmp/test.txt");
204
+ touchFile("test.tmp/test.txt", 1);
205
205
 
206
206
  checker.changed("test.tmp/test.txt");
207
- unlink("test.tmp/test.txt");
208
- system("chmod a= test.tmp");
209
- ensure(!checker.changed("test.tmp/test.txt"));
210
- system("chmod u=rwx test.tmp");
211
- ensure(checker.changed("test.tmp/test.txt"));
207
+ touchFile("test.tmp/test.txt", 2);
208
+ runShellCommand("chmod a= test.tmp");
209
+ ensure("(1)", !checker.changed("test.tmp/test.txt"));
210
+ runShellCommand("chmod u=rwx test.tmp");
211
+ ensure("(2)", checker.changed("test.tmp/test.txt"));
212
212
  }
213
213
  }
214
214
 
@@ -228,9 +228,11 @@ namespace tut {
228
228
  unlink("test.txt");
229
229
  unlink("test2.txt");
230
230
  unlink("test3.txt");
231
- ensure("test2.txt is still in the file list", checker.changed("test2.txt"));
232
- ensure("test3.txt is still in the file list", checker.changed("test3.txt"));
233
- ensure("test.txt is removed from the file list", !checker.changed("test.txt"));
231
+ ensure("test2.txt is still in the file list", checker.knows("test2.txt"));
232
+ ensure("test2.txt is not considered changed", !checker.changed("test2.txt"));
233
+ ensure("test3.txt is still in the file list", checker.knows("test3.txt"));
234
+ ensure("test3.txt is not considered changed", !checker.changed("test3.txt"));
235
+ ensure("test.txt is removed from the file list", !checker.knows("test.txt"));
234
236
  }
235
237
 
236
238
  TEST_METHOD(14) {
@@ -1,5 +1,5 @@
1
1
  #include "TestSupport.h"
2
- #include "LoggingAgent/FilterSupport.h"
2
+ #include "agents/LoggingAgent/FilterSupport.h"
3
3
 
4
4
  #include <boost/bind.hpp>
5
5
  #include <boost/shared_ptr.hpp>
@@ -159,13 +159,13 @@ namespace tut {
159
159
  TEST_METHOD(15) {
160
160
  // String begin and end quote characters must match.
161
161
  try {
162
- Filter("uri == 'hello world\"");
162
+ (void) Filter("uri == 'hello world\"");
163
163
  fail("Syntax error expected");
164
164
  } catch (const SyntaxError &) {
165
165
  // Pass.
166
166
  }
167
167
  try {
168
- Filter("uri == \"hello world'");
168
+ (void) Filter("uri == \"hello world'");
169
169
  fail("Syntax error expected");
170
170
  } catch (const SyntaxError &) {
171
171
  // Pass.
@@ -177,13 +177,13 @@ namespace tut {
177
177
  ctx.uri = "hello world";
178
178
  ensure(Filter("uri =~ %r{hello}").run(ctx));
179
179
  try {
180
- Filter("uri =~ /hello}");
180
+ (void) Filter("uri =~ /hello}");
181
181
  fail("Syntax error expected");
182
182
  } catch (const SyntaxError &) {
183
183
  // Pass.
184
184
  }
185
185
  try {
186
- Filter("uri =~ %r{hello/");
186
+ (void) Filter("uri =~ %r{hello/");
187
187
  fail("Syntax error expected");
188
188
  } catch (const SyntaxError &) {
189
189
  // Pass.
@@ -475,9 +475,16 @@ namespace tut {
475
475
  Pipe p = createPipe();
476
476
  unsigned long long startTime = SystemTime::getUsec();
477
477
  unsigned long long timeout = 30000;
478
+ char data1[1024], data2[1024];
479
+ StaticString data[] = {
480
+ StaticString(data1, sizeof(data1) - 1),
481
+ StaticString(data2, sizeof(data2) - 1)
482
+ };
483
+ memset(data1, 'x', sizeof(data1));
484
+ memset(data2, 'y', sizeof(data2));
485
+
478
486
  try {
479
- StaticString data[] = { "hello", "world" };
480
- for (int i = 0; i < 1024 * 1024; i++) {
487
+ for (int i = 0; i < 1024; i++) {
481
488
  gatheredWrite(p[1], data, 2, &timeout);
482
489
  }
483
490
  fail("TimeoutException expected");
@@ -804,7 +811,7 @@ namespace tut {
804
811
  SocketPair sockets = createUnixSocketPair();
805
812
  Pipe pipes = createPipe();
806
813
  writeFileDescriptor(sockets[0], pipes[1]);
807
- FileDescriptor fd = readFileDescriptor(sockets[1]);
814
+ FileDescriptor fd(readFileDescriptor(sockets[1]));
808
815
  writeExact(fd, "hello");
809
816
  char buf[6];
810
817
  ensure_equals(readExact(pipes[0], buf, 5), 5u);
@@ -820,7 +827,7 @@ namespace tut {
820
827
  unsigned long long timeout = 30000;
821
828
  unsigned long long startTime = SystemTime::getUsec();
822
829
  try {
823
- FileDescriptor fd = readFileDescriptor(sockets[0], &timeout);
830
+ FileDescriptor fd(readFileDescriptor(sockets[0], &timeout));
824
831
  fail("TimeoutException expected");
825
832
  } catch (const TimeoutException &) {
826
833
  unsigned long long elapsed = SystemTime::getUsec() - startTime;
@@ -1,4 +1,4 @@
1
- #include "TestSupport.h"
1
+ #include <TestSupport.h>
2
2
  #include <MessageReadersWriters.h>
3
3
  #include <cstdlib>
4
4
  #include <alloca.h>
@@ -4,7 +4,7 @@
4
4
  #include <boost/bind.hpp>
5
5
 
6
6
  #include "MessageServer.h"
7
- #include "ApplicationPool/Client.h"
7
+ #include "MessageClient.h"
8
8
  #include "Utils.h"
9
9
  #include <string>
10
10
  #include <cstring>
@@ -12,7 +12,6 @@
12
12
  #include <errno.h>
13
13
 
14
14
  using namespace Passenger;
15
- using namespace Passenger::ApplicationPool;
16
15
  using namespace boost;
17
16
  using namespace std;
18
17
 
@@ -21,6 +20,7 @@ namespace tut {
21
20
  ServerInstanceDirPtr serverInstanceDir;
22
21
  ServerInstanceDir::GenerationPtr generation;
23
22
  string socketFilename;
23
+ string socketAddress;
24
24
  AccountsDatabasePtr accountsDatabase;
25
25
  AccountPtr clientAccount;
26
26
  shared_ptr<MessageServer> server;
@@ -29,6 +29,7 @@ namespace tut {
29
29
  MessageServerTest() {
30
30
  createServerInstanceDirAndGeneration(serverInstanceDir, generation);
31
31
  socketFilename = generation->getPath() + "/socket";
32
+ socketAddress = "unix:" + socketFilename;
32
33
  accountsDatabase = ptr(new AccountsDatabase());
33
34
  clientAccount = accountsDatabase->add("test", "12345", false);
34
35
 
@@ -45,40 +46,40 @@ namespace tut {
45
46
  Passenger::setLogLevel(0);
46
47
  }
47
48
 
48
- class SlowClient: public Client {
49
+ class SlowClient: public MessageClient {
49
50
  private:
50
51
  unsigned int timeToSendUsername;
51
52
  unsigned int timeToSendPassword;
52
53
 
53
54
  protected:
54
- virtual void sendUsername(MessageChannel &channel, const string &username) {
55
+ virtual void sendUsername(int fd, const StaticString &username, unsigned long long *timeout) {
55
56
  if (timeToSendUsername > 0) {
56
57
  usleep(timeToSendUsername * 1000);
57
58
  }
58
- channel.writeScalar(username);
59
+ writeScalarMessage(fd, username);
59
60
  }
60
61
 
61
- virtual void sendPassword(MessageChannel &channel, const StaticString &userSuppliedPassword) {
62
+ virtual void sendPassword(int fd, const StaticString &userSuppliedPassword, unsigned long long *timeout) {
62
63
  if (timeToSendPassword > 0) {
63
64
  usleep(timeToSendPassword * 1000);
64
65
  }
65
- channel.writeScalar(userSuppliedPassword.c_str(), userSuppliedPassword.size());
66
+ writeScalarMessage(fd, userSuppliedPassword);
66
67
  }
67
68
 
68
69
  public:
69
70
  SlowClient(unsigned int timeToSendUsername,
70
71
  unsigned int timeToSendPassword)
71
- : Client()
72
+ : MessageClient()
72
73
  {
73
74
  this->timeToSendUsername = timeToSendUsername;
74
75
  this->timeToSendPassword = timeToSendPassword;
75
76
  }
76
77
  };
77
78
 
78
- class CustomClient: public Client {
79
+ class CustomClient: public MessageClient {
79
80
  public:
80
81
  CustomClient *sendText(const string &text) {
81
- data->channel.write(text.c_str(), NULL);
82
+ write(text.c_str(), NULL);
82
83
  return this;
83
84
  }
84
85
  };
@@ -153,19 +154,19 @@ namespace tut {
153
154
  accountsDatabase->add("hashed_user", Account::createHash("67890"), true);
154
155
 
155
156
  try {
156
- Client().connect(socketFilename, "testt", "12345");
157
+ MessageClient().connect(socketAddress, "testt", "12345");
157
158
  fail("SecurityException expected when invalid username is given");
158
159
  } catch (const SecurityException &) {
159
160
  // Pass.
160
161
  }
161
162
  try {
162
- Client().connect(socketFilename, "test", "123456");
163
+ MessageClient().connect(socketAddress, "test", "123456");
163
164
  fail("SecurityException expected when invalid password is given for an account with plain text password");
164
165
  } catch (const SecurityException &) {
165
166
  // Pass.
166
167
  }
167
168
  try {
168
- Client().connect(socketFilename, "test", "678900");
169
+ MessageClient().connect(socketAddress, "test", "678900");
169
170
  fail("SecurityException expected when invalid password is given for an account with hashed password");
170
171
  } catch (const SecurityException &) {
171
172
  // Pass.
@@ -175,14 +176,14 @@ namespace tut {
175
176
  TEST_METHOD(2) {
176
177
  // It supports hashed passwords.
177
178
  accountsDatabase->add("hashed_user", Account::createHash("67890"), true);
178
- Client().connect(socketFilename, "hashed_user", "67890"); // Should not throw exception.
179
+ MessageClient().connect(socketAddress, "hashed_user", "67890"); // Should not throw exception.
179
180
  }
180
181
 
181
182
  TEST_METHOD(3) {
182
183
  // It disconnects the client if the client does not supply a username and
183
184
  // password within a time limit.
184
185
  Passenger::setLogLevel(-1);
185
- server->setLoginTimeout(40000);
186
+ server->setLoginTimeout(30000);
186
187
 
187
188
  /* These can throw either an IOException or SystemException:
188
189
  * - An IOException is raised when connect() encounters EOF.
@@ -193,7 +194,7 @@ namespace tut {
193
194
 
194
195
  try {
195
196
  // This client takes too much time on sending the username.
196
- SlowClient(50, 0).connect(socketFilename, "test", "12345");
197
+ SlowClient(50, 0).connect(socketAddress, "test", "12345");
197
198
  fail("IOException or SystemException expected (1).");
198
199
  } catch (const IOException &e) {
199
200
  // Pass.
@@ -203,7 +204,7 @@ namespace tut {
203
204
 
204
205
  try {
205
206
  // This client takes too much time on sending the password.
206
- SlowClient(0, 50).connect(socketFilename, "test", "12345");
207
+ SlowClient(0, 50).connect(socketAddress, "test", "12345");
207
208
  fail("IOException or SystemException expected (2).");
208
209
  } catch (const IOException &e) {
209
210
  // Pass.
@@ -214,7 +215,7 @@ namespace tut {
214
215
  try {
215
216
  // This client is fast enough at sending the username and
216
217
  // password individually, but the combined time is too long.
217
- SlowClient(25, 25).connect(socketFilename, "test", "12345");
218
+ SlowClient(25, 25).connect(socketAddress, "test", "12345");
218
219
  fail("IOException or SystemException expected (3).");
219
220
  } catch (const IOException &e) {
220
221
  // Pass.
@@ -229,7 +230,7 @@ namespace tut {
229
230
  memset(username, 'x', sizeof(username));
230
231
  username[sizeof(username) - 1] = '\0';
231
232
  try {
232
- Client().connect(socketFilename, username, "1234");
233
+ MessageClient().connect(socketAddress, username, "1234");
233
234
  fail("SecurityException expected");
234
235
  } catch (const SecurityException &e) {
235
236
  // Pass.
@@ -242,7 +243,7 @@ namespace tut {
242
243
  memset(password, 'x', sizeof(password));
243
244
  password[sizeof(password) - 1] = '\0';
244
245
  try {
245
- Client().connect(socketFilename, "test", password);
246
+ MessageClient().connect(socketAddress, "test", password);
246
247
  fail("SecurityException expected");
247
248
  } catch (const SecurityException &e) {
248
249
  // Pass.
@@ -255,8 +256,8 @@ namespace tut {
255
256
  LoggingHandlerPtr handler2(new LoggingHandler());
256
257
  server->addHandler(handler1);
257
258
  server->addHandler(handler2);
258
- Client().connect(socketFilename, "test", "12345");
259
- Client().connect(socketFilename, "test", "12345");
259
+ MessageClient().connect(socketAddress, "test", "12345");
260
+ MessageClient().connect(socketAddress, "test", "12345");
260
261
 
261
262
  usleep(10000); // Give the threads some time to do work.
262
263
  ensure_equals(handler1->clientsAccepted, 2);
@@ -275,12 +276,12 @@ namespace tut {
275
276
  handler1->returnValue = false;
276
277
 
277
278
  CustomClient c1, c2;
278
- c1.connect(socketFilename, "test", "12345");
279
+ c1.connect(socketAddress, "test", "12345");
279
280
  c1.sendText("hello");
280
281
  c1.sendText(" ");
281
282
  usleep(10000); // Give the thread some time to do work.
282
283
 
283
- c2.connect(socketFilename, "test", "12345");
284
+ c2.connect(socketAddress, "test", "12345");
284
285
  c2.sendText("world");
285
286
  usleep(10000); // Give the thread some time to do work.
286
287
 
@@ -298,7 +299,7 @@ namespace tut {
298
299
  server->addHandler(handler2);
299
300
 
300
301
  CustomClient c;
301
- c.connect(socketFilename, "test", "12345");
302
+ c.connect(socketAddress, "test", "12345");
302
303
  c.sendText("hi");
303
304
  usleep(10000); // Give the thread some time to do work.
304
305
 
@@ -314,7 +315,7 @@ namespace tut {
314
315
  server->addHandler(handler2);
315
316
 
316
317
  CustomClient c;
317
- c.connect(socketFilename, "test", "12345");
318
+ c.connect(socketAddress, "test", "12345");
318
319
  c.sendText("hi");
319
320
  usleep(10000); // Give the thread some time to do work.
320
321
 
@@ -342,7 +343,7 @@ namespace tut {
342
343
 
343
344
  handler1->id = 100;
344
345
  handler2->id = 101;
345
- c1.connect(socketFilename, "test", "12345");
346
+ c1.connect(socketAddress, "test", "12345");
346
347
  c1.sendText("hi");
347
348
  usleep(10000); // Give the thread some time to do work.
348
349
  ensure_equals(handler1->latestContext->id, 100);
@@ -350,7 +351,7 @@ namespace tut {
350
351
 
351
352
  handler1->id = 200;
352
353
  handler2->id = 201;
353
- c2.connect(socketFilename, "test", "12345");
354
+ c2.connect(socketAddress, "test", "12345");
354
355
  c2.sendText("hi");
355
356
  usleep(10000); // Give the thread some time to do work.
356
357
  ensure_equals(handler1->latestContext->id, 200);
@@ -370,13 +371,13 @@ namespace tut {
370
371
  server->addHandler(handler2);
371
372
  {
372
373
  {
373
- Client().connect(socketFilename, "test", "12345");
374
+ MessageClient().connect(socketAddress, "test", "12345");
374
375
  }
375
376
  usleep(10000); // Give the threads some time to do work.
376
377
  ensure_equals(handler1->clientsDisconnected, 1);
377
378
  ensure_equals(handler2->clientsDisconnected, 1);
378
379
 
379
- Client().connect(socketFilename, "test", "12345");
380
+ MessageClient().connect(socketAddress, "test", "12345");
380
381
  }
381
382
  usleep(10000); // Give the threads some time to do work.
382
383
  ensure_equals(handler1->clientsDisconnected, 2);
@@ -0,0 +1,777 @@
1
+ #include <TestSupport.h>
2
+ #include <agents/HelperAgent/RequestHandler.h>
3
+ #include <agents/HelperAgent/RequestHandler.cpp>
4
+ #include <agents/HelperAgent/AgentOptions.h>
5
+ #include <ApplicationPool2/Pool.h>
6
+ #include <Utils/IOUtils.h>
7
+ #include <Utils/Timer.h>
8
+
9
+ #include <boost/shared_array.hpp>
10
+ #include <string>
11
+ #include <vector>
12
+ #include <map>
13
+ #include <sstream>
14
+ #include <cstdarg>
15
+ #include <sys/socket.h>
16
+
17
+ using namespace std;
18
+ using namespace boost;
19
+ using namespace Passenger;
20
+ using namespace Passenger::ApplicationPool2;
21
+
22
+ namespace tut {
23
+ struct RequestHandlerTest {
24
+ ServerInstanceDirPtr serverInstanceDir;
25
+ ServerInstanceDir::GenerationPtr generation;
26
+ string serverFilename;
27
+ FileDescriptor requestSocket;
28
+ AgentOptions agentOptions;
29
+
30
+ BackgroundEventLoop bg;
31
+ SpawnerFactoryPtr spawnerFactory;
32
+ PoolPtr pool;
33
+ shared_ptr<RequestHandler> handler;
34
+ FileDescriptor connection;
35
+ map<string, string> defaultHeaders;
36
+
37
+ string root;
38
+ string rackAppPath, wsgiAppPath;
39
+
40
+ RequestHandlerTest() {
41
+ createServerInstanceDirAndGeneration(serverInstanceDir, generation);
42
+ spawnerFactory = make_shared<SpawnerFactory>(bg.safe, *resourceLocator, generation);
43
+ pool = make_shared<Pool>(bg.safe.get(), spawnerFactory);
44
+ serverFilename = generation->getPath() + "/server";
45
+ requestSocket = createUnixServer(serverFilename);
46
+ setNonBlocking(requestSocket);
47
+
48
+ agentOptions.passengerRoot = resourceLocator->getRoot();
49
+ root = resourceLocator->getRoot();
50
+ rackAppPath = root + "/test/stub/rack";
51
+ wsgiAppPath = root + "/test/stub/wsgi";
52
+ defaultHeaders["PASSENGER_LOAD_SHELL_ENVVARS"] = "false";
53
+ defaultHeaders["PASSENGER_APP_TYPE"] = "wsgi";
54
+ defaultHeaders["PASSENGER_SPAWN_METHOD"] = "direct";
55
+ defaultHeaders["REQUEST_METHOD"] = "GET";
56
+ }
57
+
58
+ ~RequestHandlerTest() {
59
+ setLogLevel(0);
60
+ unlink(serverFilename.c_str());
61
+ handler.reset();
62
+ pool->destroy();
63
+ pool.reset();
64
+ }
65
+
66
+ void init() {
67
+ handler = make_shared<RequestHandler>(bg.safe, requestSocket, pool, agentOptions);
68
+ bg.start();
69
+ }
70
+
71
+ FileDescriptor &connect() {
72
+ connection = connectToUnixServer(serverFilename);
73
+ return connection;
74
+ }
75
+
76
+ void sendHeaders(const map<string, string> &headers, ...) {
77
+ va_list ap;
78
+ const char *arg;
79
+ map<string, string>::const_iterator it;
80
+ vector<StaticString> args;
81
+
82
+ for (it = headers.begin(); it != headers.end(); it++) {
83
+ args.push_back(StaticString(it->first.data(), it->first.size() + 1));
84
+ args.push_back(StaticString(it->second.data(), it->second.size() + 1));
85
+ }
86
+
87
+ va_start(ap, headers);
88
+ while ((arg = va_arg(ap, const char *)) != NULL) {
89
+ args.push_back(StaticString(arg, strlen(arg) + 1));
90
+ }
91
+ va_end(ap);
92
+
93
+ shared_array<StaticString> args_array(new StaticString[args.size() + 2]);
94
+ unsigned int totalSize = 0;
95
+ for (unsigned int i = 0; i < args.size(); i++) {
96
+ args_array[i + 1] = args[i];
97
+ totalSize += args[i].size();
98
+ }
99
+ char totalSizeString[10];
100
+ snprintf(totalSizeString, sizeof(totalSizeString), "%u:", totalSize);
101
+ args_array[0] = StaticString(totalSizeString);
102
+ args_array[args.size() + 1] = ",";
103
+
104
+ gatheredWrite(connection, args_array.get(), args.size() + 2, NULL);
105
+ }
106
+
107
+ string stripHeaders(const string &str) {
108
+ string::size_type pos = str.find("\r\n\r\n");
109
+ if (pos == string::npos) {
110
+ return str;
111
+ } else {
112
+ string result = str;
113
+ result.erase(0, pos + 4);
114
+ return result;
115
+ }
116
+ }
117
+
118
+ string inspect() {
119
+ string result;
120
+ bg.safe->runSync(boost::bind(&RequestHandlerTest::real_inspect, this, &result));
121
+ return result;
122
+ }
123
+
124
+ void real_inspect(string *result) {
125
+ stringstream stream;
126
+ handler->inspect(stream);
127
+ *result = stream.str();
128
+ }
129
+
130
+ static void writeBody(FileDescriptor conn, string body) {
131
+ try {
132
+ writeExact(conn, body);
133
+ } catch (const SystemException &e) {
134
+ if (e.code() == EPIPE) {
135
+ // Ignore.
136
+ } else {
137
+ throw;
138
+ }
139
+ }
140
+ }
141
+ };
142
+
143
+ DEFINE_TEST_GROUP(RequestHandlerTest);
144
+
145
+ TEST_METHOD(1) {
146
+ // Test one normal request.
147
+ init();
148
+ connect();
149
+ sendHeaders(defaultHeaders,
150
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
151
+ "PATH_INFO", "/",
152
+ NULL);
153
+ string response = readAll(connection);
154
+ string body = stripHeaders(response);
155
+ ensure("Status line is correct", containsSubstring(response, "HTTP/1.1 200 OK\r\n"));
156
+ ensure("Headers are correct", containsSubstring(response, "Content-Type: text/html\r\n"));
157
+ ensure("Contains a Status header", containsSubstring(response, "Status: 200 OK\r\n"));
158
+ ensure_equals(body, "hello <b>world</b>");
159
+ }
160
+
161
+ TEST_METHOD(2) {
162
+ // Test multiple normal requests.
163
+ init();
164
+ for (int i = 0; i < 10; i++) {
165
+ connect();
166
+ sendHeaders(defaultHeaders,
167
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
168
+ "PATH_INFO", "/",
169
+ NULL);
170
+ string response = readAll(connection);
171
+ string body = stripHeaders(response);
172
+ ensure("Status line is correct", containsSubstring(response, "HTTP/1.1 200 OK\r\n"));
173
+ ensure("Headers are correct", containsSubstring(response, "Content-Type: text/html\r\n"));
174
+ ensure("Contains a Status header", containsSubstring(response, "Status: 200 OK\r\n"));
175
+ ensure_equals(body, "hello <b>world</b>");
176
+ }
177
+ }
178
+
179
+ TEST_METHOD(3) {
180
+ // Test sending request data in pieces.
181
+ defaultHeaders["PASSENGER_APP_ROOT"] = wsgiAppPath;
182
+ defaultHeaders["PATH_INFO"] = "/";
183
+
184
+ string request;
185
+ map<string, string>::const_iterator it, end = defaultHeaders.end();
186
+ for (it = defaultHeaders.begin(); it != end; it++) {
187
+ request.append(it->first);
188
+ request.append(1, '\0');
189
+ request.append(it->second);
190
+ request.append(1, '\0');
191
+ }
192
+ request = toString(request.size()) + ":" + request;
193
+ request.append(",");
194
+
195
+ init();
196
+ connect();
197
+ string::size_type i = 0;
198
+ while (i < request.size()) {
199
+ const string piece = const_cast<const string &>(request).substr(i, 5);
200
+ writeExact(connection, piece);
201
+ usleep(10000);
202
+ i += piece.size();
203
+ }
204
+
205
+ string response = readAll(connection);
206
+ string body = stripHeaders(response);
207
+ ensure("Status line is correct", containsSubstring(response, "HTTP/1.1 200 OK\r\n"));
208
+ ensure("Headers are correct", containsSubstring(response, "Content-Type: text/html\r\n"));
209
+ ensure("Contains a Status header", containsSubstring(response, "Status: 200 OK\r\n"));
210
+ ensure_equals(body, "hello <b>world</b>");
211
+ }
212
+
213
+ TEST_METHOD(4) {
214
+ // It denies access if the connect password is wrong.
215
+ agentOptions.requestSocketPassword = "hello world";
216
+ setLogLevel(-1);
217
+ init();
218
+
219
+ connect();
220
+ writeExact(connection, "hello world");
221
+ sendHeaders(defaultHeaders,
222
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
223
+ "PATH_INFO", "/",
224
+ NULL
225
+ );
226
+ ensure(containsSubstring(readAll(connection), "hello <b>world</b>"));
227
+
228
+ connect();
229
+ try {
230
+ sendHeaders(defaultHeaders,
231
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
232
+ "PATH_INFO", "/",
233
+ NULL
234
+ );
235
+ } catch (const SystemException &e) {
236
+ ensure_equals(e.code(), EPIPE);
237
+ return;
238
+ }
239
+ string response;
240
+ try {
241
+ response = readAll(connection);
242
+ } catch (const SystemException &e) {
243
+ ensure_equals(e.code(), ECONNRESET);
244
+ return;
245
+ }
246
+ ensure_equals(response, "");
247
+ }
248
+
249
+ TEST_METHOD(5) {
250
+ // It disconnects us if the connect password is not sent within a certain time.
251
+ agentOptions.requestSocketPassword = "hello world";
252
+ setLogLevel(-1);
253
+ handler = make_shared<RequestHandler>(bg.safe, requestSocket, pool, agentOptions);
254
+ handler->connectPasswordTimeout = 40;
255
+ bg.start();
256
+
257
+ connect();
258
+ Timer timer;
259
+ readAll(connection);
260
+ timer.stop();
261
+ ensure(timer.elapsed() <= 60);
262
+ }
263
+
264
+ TEST_METHOD(6) {
265
+ // It works correct if the connect password is sent in pieces.
266
+ agentOptions.requestSocketPassword = "hello world";
267
+ init();
268
+ connect();
269
+ writeExact(connection, "hello");
270
+ usleep(10000);
271
+ writeExact(connection, " world");
272
+ usleep(10000);
273
+ sendHeaders(defaultHeaders,
274
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
275
+ "PATH_INFO", "/",
276
+ NULL
277
+ );
278
+ ensure(containsSubstring(readAll(connection), "hello <b>world</b>"));
279
+ }
280
+
281
+ TEST_METHOD(7) {
282
+ // It closes the connection with the application if the client has closed the connection.
283
+ init();
284
+ connect();
285
+ sendHeaders(defaultHeaders,
286
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
287
+ "PATH_INFO", "/stream",
288
+ NULL
289
+ );
290
+ BufferedIO io(connection);
291
+ ensure_equals(io.readLine(), "HTTP/1.1 200 OK\r\n");
292
+ ensure_equals(pool->getProcessCount(), 1u);
293
+ SuperGroupPtr superGroup = pool->superGroups.get(wsgiAppPath);
294
+ ProcessPtr process = superGroup->defaultGroup->processes.front();
295
+ ensure_equals(process->sessions, 1);
296
+ connection.close();
297
+ EVENTUALLY(5,
298
+ result = process->sessions == 0;
299
+ );
300
+ }
301
+
302
+ TEST_METHOD(10) {
303
+ // If the app crashes at startup without an error page then it renders
304
+ // a generic error page.
305
+ TempDir tempdir("tmp.handler");
306
+ writeFile("tmp.handler/start.rb",
307
+ "STDERR.puts 'I have failed'");
308
+
309
+ setLogLevel(-2);
310
+ spawnerFactory->forwardStderr = false;
311
+ init();
312
+ connect();
313
+ sendHeaders(defaultHeaders,
314
+ "PASSENGER_APP_ROOT", (root + "/test/tmp.handler").c_str(),
315
+ "PASSENGER_APP_TYPE", "",
316
+ "PASSENGER_START_COMMAND", ("ruby\1" + root + "/test/tmp.handler/start.rb").c_str(),
317
+ "PATH_INFO", "/",
318
+ NULL);
319
+ string response = readAll(connection);
320
+ ensure(containsSubstring(response, "HTTP/1.1 500 Internal Server Error\r\n"));
321
+ ensure(containsSubstring(response, "Status: 500 Internal Server Error\r\n"));
322
+ ensure(containsSubstring(response, "I have failed"));
323
+ }
324
+
325
+ TEST_METHOD(11) {
326
+ // If the app crashes at startup with an error page then it renders
327
+ // a friendly error page.
328
+ TempDir tempdir("tmp.handler");
329
+ writeFile("tmp.handler/start.rb",
330
+ "STDERR.puts 'Error'\n"
331
+ "STDERR.puts\n"
332
+ "STDERR.puts 'I have failed'\n");
333
+
334
+ setLogLevel(-2);
335
+ spawnerFactory->forwardStderr = false;
336
+ init();
337
+ connect();
338
+ sendHeaders(defaultHeaders,
339
+ "PASSENGER_APP_ROOT", (root + "/test/tmp.handler").c_str(),
340
+ "PASSENGER_APP_TYPE", "",
341
+ "PASSENGER_START_COMMAND", ("ruby\1" + root + "/test/tmp.handler/start.rb").c_str(),
342
+ "PATH_INFO", "/",
343
+ NULL);
344
+ string response = readAll(connection);
345
+ ensure(containsSubstring(response, "HTTP/1.1 500 Internal Server Error\r\n"));
346
+ ensure(containsSubstring(response, "Status: 500 Internal Server Error\r\n"));
347
+ ensure(containsSubstring(response, "Content-Type: text/html; charset=UTF-8\r\n"));
348
+ ensure(containsSubstring(response, "<html>"));
349
+ ensure(containsSubstring(response, "I have failed"));
350
+ }
351
+
352
+ TEST_METHOD(12) {
353
+ // If spawning fails because of an internal error then it reports the error appropriately.
354
+ TempDir tempdir("tmp.handler");
355
+ writeFile("tmp.handler/start.rb", "");
356
+
357
+ setLogLevel(-2);
358
+ spawnerFactory->forwardStderr = false;
359
+ init();
360
+ connect();
361
+ sendHeaders(defaultHeaders,
362
+ "PASSENGER_APP_ROOT", (root + "/test/tmp.handler").c_str(),
363
+ "PASSENGER_APP_TYPE", "",
364
+ "PASSENGER_START_COMMAND", ("ruby\1" + root + "/test/tmp.handler/start.rb").c_str(),
365
+ "PASSENGER_RAISE_INTERNAL_ERROR", "true",
366
+ "PATH_INFO", "/",
367
+ NULL);
368
+ string response = readAll(connection);
369
+ ensure(containsSubstring(response, "HTTP/1.1 500 Internal Server Error\r\n"));
370
+ ensure(containsSubstring(response, "Status: 500 Internal Server Error\r\n"));
371
+ ensure(containsSubstring(response, "Content-Type: text/html; charset=UTF-8\r\n"));
372
+ ensure(containsSubstring(response, "<html>"));
373
+ ensure(containsSubstring(response, "An internal error occurred while trying to spawn the application."));
374
+ ensure(containsSubstring(response, "Passenger:<wbr>:<wbr>RuntimeException"));
375
+ ensure(containsSubstring(response, "An internal error!"));
376
+ ensure(containsSubstring(response, "Spawner.h"));
377
+ }
378
+
379
+ TEST_METHOD(13) {
380
+ // Error pages respect the PASSENGER_STATUS_LINE option.
381
+ TempDir tempdir("tmp.handler");
382
+ writeFile("tmp.handler/start.rb",
383
+ "STDERR.puts 'I have failed'");
384
+
385
+ setLogLevel(-2);
386
+ spawnerFactory->forwardStderr = false;
387
+ init();
388
+ connect();
389
+ sendHeaders(defaultHeaders,
390
+ "PASSENGER_APP_ROOT", (root + "/test/tmp.handler").c_str(),
391
+ "PASSENGER_APP_TYPE", "",
392
+ "PASSENGER_START_COMMAND", ("ruby\1" + root + "/test/tmp.handler/start.rb").c_str(),
393
+ "PASSENGER_STATUS_LINE", "false",
394
+ "PATH_INFO", "/",
395
+ NULL);
396
+ string response = readAll(connection);
397
+ ensure(!containsSubstring(response, "HTTP/1.1 "));
398
+ ensure(containsSubstring(response, "Status: 500 Internal Server Error\r\n"));
399
+ ensure(containsSubstring(response, "I have failed"));
400
+ }
401
+
402
+ TEST_METHOD(14) {
403
+ // If PASSENGER_FRIENDLY_ERROR_PAGES is false then it does not render
404
+ // a friendly error page.
405
+ TempDir tempdir("tmp.handler");
406
+ writeFile("tmp.handler/start.rb",
407
+ "STDERR.puts 'Error'\n"
408
+ "STDERR.puts\n"
409
+ "STDERR.puts 'I have failed'\n");
410
+
411
+ setLogLevel(-2);
412
+ spawnerFactory->forwardStderr = false;
413
+ init();
414
+ connect();
415
+ sendHeaders(defaultHeaders,
416
+ "PASSENGER_APP_ROOT", (root + "/test/tmp.handler").c_str(),
417
+ "PASSENGER_APP_TYPE", "",
418
+ "PASSENGER_START_COMMAND", ("ruby\1" + root + "/test/tmp.handler/start.rb").c_str(),
419
+ "PASSENGER_FRIENDLY_ERROR_PAGES", "false",
420
+ "PATH_INFO", "/",
421
+ NULL);
422
+ string response = readAll(connection);
423
+ ensure(containsSubstring(response, "HTTP/1.1 500 Internal Server Error\r\n"));
424
+ ensure(containsSubstring(response, "Status: 500 Internal Server Error\r\n"));
425
+ ensure(containsSubstring(response, "Content-Type: text/html; charset=UTF-8\r\n"));
426
+ ensure(containsSubstring(response, "<html>"));
427
+ ensure(!containsSubstring(response, "I have failed"));
428
+ ensure(containsSubstring(response, "We're sorry, but something went wrong"));
429
+ }
430
+
431
+ TEST_METHOD(20) {
432
+ // It streams the request body to the application.
433
+ DeleteFileEventually file("tmp.output");
434
+
435
+ init();
436
+ connect();
437
+ sendHeaders(defaultHeaders,
438
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
439
+ "PATH_INFO", "/upload",
440
+ "HTTP_X_OUTPUT", (root + "/test/tmp.output").c_str(),
441
+ NULL);
442
+ writeExact(connection, "hello\n");
443
+ EVENTUALLY(5,
444
+ result = fileExists("tmp.output") && readAll("tmp.output") == "hello\n";
445
+ );
446
+ writeExact(connection, "world\n");
447
+ EVENTUALLY(3,
448
+ result = readAll("tmp.output") == "hello\nworld\n";
449
+ );
450
+ shutdown(connection, SHUT_WR);
451
+ ensure_equals(stripHeaders(readAll(connection)), "ok");
452
+ }
453
+
454
+ TEST_METHOD(21) {
455
+ // It buffers the request body if PASSENGER_BUFFERING is true.
456
+ DeleteFileEventually file("tmp.output");
457
+
458
+ init();
459
+ connect();
460
+ sendHeaders(defaultHeaders,
461
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
462
+ "PASSENGER_BUFFERING", "true",
463
+ "PATH_INFO", "/upload",
464
+ "HTTP_X_OUTPUT", (root + "/test/tmp.output").c_str(),
465
+ NULL);
466
+ writeExact(connection, "hello\n");
467
+ SHOULD_NEVER_HAPPEN(200,
468
+ result = fileExists("tmp.output");
469
+ );
470
+ writeExact(connection, "world\n");
471
+ SHOULD_NEVER_HAPPEN(200,
472
+ result = fileExists("tmp.output");
473
+ );
474
+ shutdown(connection, SHUT_WR);
475
+ ensure_equals(stripHeaders(readAll(connection)), "ok");
476
+ }
477
+
478
+ TEST_METHOD(22) {
479
+ set_test_name("Test buffering of large request bodies that fit in neither the socket "
480
+ "buffer nor the FileBackedPipe memory buffer, and that the application "
481
+ "cannot read quickly enough.");
482
+
483
+ DeleteFileEventually d1("/tmp/wait.txt");
484
+ DeleteFileEventually d2("/tmp/output.txt");
485
+
486
+ // 2.6 MB of request body. Guaranteed not to fit in any socket buffer.
487
+ string requestBody;
488
+ for (int i = 0; i < 204800; i++) {
489
+ requestBody.append("hello world!\n");
490
+ }
491
+
492
+ init();
493
+ connect();
494
+ sendHeaders(defaultHeaders,
495
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
496
+ "PATH_INFO", "/upload",
497
+ "PASSENGER_BUFFERING", "true",
498
+ "HTTP_X_WAIT_FOR_FILE", "/tmp/wait.txt",
499
+ "HTTP_X_OUTPUT", "/tmp/output.txt",
500
+ NULL);
501
+
502
+ // Should not block.
503
+ writeExact(connection, requestBody);
504
+ shutdown(connection, SHUT_WR);
505
+
506
+ EVENTUALLY(5,
507
+ result = containsSubstring(inspect(), "session initiated = true");
508
+ );
509
+ touchFile("/tmp/wait.txt");
510
+
511
+ string result = stripHeaders(readAll(connection));
512
+ ensure_equals(result, "ok");
513
+ struct stat buf;
514
+ ensure(stat("/tmp/output.txt", &buf) == 0);
515
+ ensure_equals(buf.st_size, (off_t) requestBody.size());
516
+ }
517
+
518
+ TEST_METHOD(30) {
519
+ // It replaces HTTP_CONTENT_LENGTH with CONTENT_LENGTH.
520
+ init();
521
+ connect();
522
+ sendHeaders(defaultHeaders,
523
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
524
+ "PATH_INFO", "/env",
525
+ "HTTP_CONTENT_LENGTH", "5",
526
+ NULL);
527
+ writeExact(connection, "hello");
528
+ string response = readAll(connection);
529
+ ensure(containsSubstring(response, "CONTENT_LENGTH = 5\n"));
530
+ ensure(!containsSubstring(response, "HTTP_CONTENT_LENGTH"));
531
+ }
532
+
533
+ TEST_METHOD(31) {
534
+ // It replaces HTTP_CONTENT_TYPE with CONTENT_TYPE.
535
+ init();
536
+ connect();
537
+ sendHeaders(defaultHeaders,
538
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
539
+ "PATH_INFO", "/env",
540
+ "HTTP_CONTENT_TYPE", "application/json",
541
+ NULL);
542
+ string response = readAll(connection);
543
+ ensure(containsSubstring(response, "CONTENT_TYPE = application/json\n"));
544
+ ensure(!containsSubstring(response, "HTTP_CONTENT_TYPE"));
545
+ }
546
+
547
+ TEST_METHOD(35) {
548
+ // The response doesn't contain an HTTP status line if PASSENGER_STATUS_LINE is false.
549
+ init();
550
+ connect();
551
+ sendHeaders(defaultHeaders,
552
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
553
+ "PASSENGER_STATUS_LINE", "false",
554
+ "PATH_INFO", "/",
555
+ NULL);
556
+ string response = readAll(connection);
557
+ ensure(!containsSubstring(response, "HTTP/1.1 "));
558
+ ensure(containsSubstring(response, "Status: 200 OK\r\n"));
559
+ }
560
+
561
+ TEST_METHOD(36) {
562
+ // If the application outputs a status line without a reason phrase,
563
+ // then a reason phrase is automatically appended.
564
+ init();
565
+ connect();
566
+ sendHeaders(defaultHeaders,
567
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
568
+ "PATH_INFO", "/custom_status",
569
+ "HTTP_X_CUSTOM_STATUS", "201",
570
+ NULL);
571
+ string response = readAll(connection);
572
+ ensure(containsSubstring(response, "HTTP/1.1 201 Created\r\n"));
573
+ ensure(containsSubstring(response, "Status: 201 Created\r\n"));
574
+ }
575
+
576
+ TEST_METHOD(37) {
577
+ // If the application outputs a status line with a custom reason phrase,
578
+ // then that reason phrase is used.
579
+ init();
580
+ connect();
581
+ sendHeaders(defaultHeaders,
582
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
583
+ "PATH_INFO", "/custom_status",
584
+ "HTTP_X_CUSTOM_STATUS", "201 Bunnies Jump",
585
+ NULL);
586
+ string response = readAll(connection);
587
+ ensure(containsSubstring(response, "HTTP/1.1 201 Bunnies Jump\r\n"));
588
+ ensure(containsSubstring(response, "Status: 201 Bunnies Jump\r\n"));
589
+ }
590
+
591
+ TEST_METHOD(38) {
592
+ // If the application doesn't output a status line then it rejects the application response.
593
+ // TODO
594
+ }
595
+
596
+ TEST_METHOD(39) {
597
+ // Test handling of slow clients that can't receive response data fast enough (response buffering).
598
+ init();
599
+ connect();
600
+ sendHeaders(defaultHeaders,
601
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
602
+ "PATH_INFO", "/blob",
603
+ "HTTP_X_SIZE", "10485760",
604
+ NULL);
605
+ EVENTUALLY(10,
606
+ result = containsSubstring(inspect(), "appInput reachedEnd = true");
607
+ );
608
+ string result = stripHeaders(readAll(connection));
609
+ ensure_equals(result.size(), 10485760u);
610
+ const char *data = result.data();
611
+ const char *end = result.data() + result.size();
612
+ while (data < end) {
613
+ ensure_equals(*data, 'x');
614
+ data++;
615
+ }
616
+ }
617
+
618
+ TEST_METHOD(40) {
619
+ set_test_name("Test that RequestHandler does not read more than CONTENT_LENGTH bytes "
620
+ "from the client body (when buffering is on and request body is large).");
621
+
622
+ DeleteFileEventually d("/tmp/output.txt");
623
+
624
+ // 2.6 MB of request body. Guaranteed not to fit in any socket buffer.
625
+ string requestBody;
626
+ for (int i = 0; i < 204800; i++) {
627
+ requestBody.append("hello world!\n");
628
+ }
629
+
630
+ init();
631
+ connect();
632
+ sendHeaders(defaultHeaders,
633
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
634
+ "PATH_INFO", "/upload",
635
+ "CONTENT_LENGTH", toString(requestBody.size()).c_str(),
636
+ "PASSENGER_BUFFERING", "true",
637
+ "HTTP_X_OUTPUT", "/tmp/output.txt",
638
+ NULL);
639
+ writeExact(connection, requestBody);
640
+
641
+ string result = stripHeaders(readAll(connection));
642
+ ensure_equals(result, "ok");
643
+ struct stat buf;
644
+ ensure(stat("/tmp/output.txt", &buf) == 0);
645
+ ensure_equals(buf.st_size, (off_t) requestBody.size());
646
+ }
647
+
648
+ TEST_METHOD(41) {
649
+ set_test_name("Test that RequestHandler does not read more than CONTENT_LENGTH bytes "
650
+ "from the client body (when buffering is on and request body is small).");
651
+
652
+ DeleteFileEventually d("/tmp/output.txt");
653
+ string requestBody = "hello world";
654
+
655
+ init();
656
+ connect();
657
+ sendHeaders(defaultHeaders,
658
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
659
+ "PATH_INFO", "/upload",
660
+ "CONTENT_LENGTH", toString(requestBody.size()).c_str(),
661
+ "PASSENGER_BUFFERING", "true",
662
+ "HTTP_X_OUTPUT", "/tmp/output.txt",
663
+ NULL);
664
+ writeExact(connection, requestBody);
665
+
666
+ string result = stripHeaders(readAll(connection));
667
+ ensure_equals(result, "ok");
668
+ struct stat buf;
669
+ ensure(stat("/tmp/output.txt", &buf) == 0);
670
+ ensure_equals(buf.st_size, (off_t) requestBody.size());
671
+ }
672
+
673
+ TEST_METHOD(42) {
674
+ set_test_name("Test that RequestHandler does not read more than CONTENT_LENGTH bytes "
675
+ "from the client body (when buffering is off and request body is large).");
676
+
677
+ DeleteFileEventually d("/tmp/output.txt");
678
+
679
+ // 2 MB of request body. Guaranteed not to fit in any socket buffer.
680
+ string requestBody;
681
+ for (int i = 0; i < 102400; i++) {
682
+ char buf[100];
683
+ snprintf(buf, sizeof(buf), "%06d: hello world!\n", i);
684
+ requestBody.append(buf);
685
+ }
686
+
687
+ init();
688
+ connect();
689
+ sendHeaders(defaultHeaders,
690
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
691
+ "PATH_INFO", "/upload",
692
+ "CONTENT_LENGTH", toString(requestBody.size()).c_str(),
693
+ "HTTP_X_OUTPUT", "/tmp/output.txt",
694
+ NULL);
695
+
696
+ TempThread thr(boost::bind(RequestHandlerTest::writeBody, connection, requestBody));
697
+
698
+ string result = stripHeaders(readAll(connection));
699
+ ensure_equals(result, "ok");
700
+ struct stat buf;
701
+ ensure(stat("/tmp/output.txt", &buf) == 0);
702
+ ensure_equals(buf.st_size, (off_t) requestBody.size());
703
+ }
704
+
705
+ TEST_METHOD(43) {
706
+ set_test_name("Test that RequestHandler does not read more than CONTENT_LENGTH bytes "
707
+ "from the client body (when buffering is off and request body is small).");
708
+
709
+ DeleteFileEventually d("/tmp/output.txt");
710
+ string requestBody = "hello world";
711
+
712
+ init();
713
+ connect();
714
+ sendHeaders(defaultHeaders,
715
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
716
+ "PATH_INFO", "/upload",
717
+ "CONTENT_LENGTH", toString(requestBody.size()).c_str(),
718
+ "HTTP_X_OUTPUT", "/tmp/output.txt",
719
+ NULL);
720
+
721
+ TempThread thr(boost::bind(RequestHandlerTest::writeBody, connection, requestBody));
722
+
723
+ string result = stripHeaders(readAll(connection));
724
+ ensure_equals(result, "ok");
725
+ struct stat buf;
726
+ ensure(stat("/tmp/output.txt", &buf) == 0);
727
+ ensure_equals(buf.st_size, (off_t) requestBody.size());
728
+ }
729
+
730
+ TEST_METHOD(44) {
731
+ set_test_name("Test that RequestHandler does not pass any client body data when CONTENT_LENGTH == 0 (when buffering is on).");
732
+
733
+ DeleteFileEventually d("/tmp/output.txt");
734
+
735
+ init();
736
+ connect();
737
+ sendHeaders(defaultHeaders,
738
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
739
+ "PATH_INFO", "/upload",
740
+ "CONTENT_LENGTH", "0",
741
+ "PASSENGER_BUFFERING", "true",
742
+ "HTTP_X_OUTPUT", "/tmp/output.txt",
743
+ NULL);
744
+ writeExact(connection, "hello world");
745
+
746
+ string result = stripHeaders(readAll(connection));
747
+ ensure_equals(result, "ok");
748
+ struct stat buf;
749
+ ensure(stat("/tmp/output.txt", &buf) == 0);
750
+ ensure_equals(buf.st_size, (off_t) 0);
751
+ }
752
+
753
+ TEST_METHOD(45) {
754
+ set_test_name("Test that RequestHandler does not pass any client body data when CONTENT_LENGTH == 0 (when buffering is off).");
755
+
756
+ DeleteFileEventually d("/tmp/output.txt");
757
+
758
+ init();
759
+ connect();
760
+ sendHeaders(defaultHeaders,
761
+ "PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
762
+ "PATH_INFO", "/upload",
763
+ "CONTENT_LENGTH", "0",
764
+ "HTTP_X_OUTPUT", "/tmp/output.txt",
765
+ NULL);
766
+ writeExact(connection, "hello world");
767
+
768
+ string result = stripHeaders(readAll(connection));
769
+ ensure_equals(result, "ok");
770
+ struct stat buf;
771
+ ensure(stat("/tmp/output.txt", &buf) == 0);
772
+ ensure_equals(buf.st_size, (off_t) 0);
773
+ }
774
+
775
+ // Test small response buffering.
776
+ // Test large response buffering.
777
+ }