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
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - http://www.modrails.com/
3
- * Copyright (c) 2010 Phusion
3
+ * Copyright (c) 2010, 2011, 2012 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -27,7 +27,11 @@
27
27
 
28
28
  #include <ev++.h>
29
29
  #include <vector>
30
+ #include <list>
31
+ #include <memory>
32
+ #include <climits>
30
33
  #include <boost/thread.hpp>
34
+ #include <boost/shared_ptr.hpp>
31
35
  #include <boost/function.hpp>
32
36
  #include <boost/bind.hpp>
33
37
 
@@ -43,25 +47,67 @@ using namespace boost;
43
47
  class SafeLibev {
44
48
  private:
45
49
  typedef function<void ()> Callback;
50
+
51
+ struct Command {
52
+ int id;
53
+ Callback callback;
54
+
55
+ Command(unsigned int _id, const Callback &_callback)
56
+ : id(_id),
57
+ callback(_callback)
58
+ { }
59
+ };
60
+
61
+ struct Timer {
62
+ ev_timer realTimer;
63
+ SafeLibev *self;
64
+ Callback callback;
65
+ list<Timer *>::iterator it;
66
+
67
+ Timer(SafeLibev *_self, const Callback &_callback)
68
+ : self(_self),
69
+ callback(_callback)
70
+ { }
71
+ };
46
72
 
47
73
  struct ev_loop *loop;
48
74
  pthread_t loopThread;
49
75
  ev_async async;
76
+ ev_idle idle;
77
+ list<Timer *> timers;
50
78
 
51
79
  boost::mutex syncher;
52
80
  condition_variable cond;
53
- vector<Callback> commands;
81
+ vector<Command> commands;
82
+ unsigned int nextCommandId;
54
83
 
55
84
  static void asyncHandler(EV_P_ ev_async *w, int revents) {
56
85
  SafeLibev *self = (SafeLibev *) w->data;
57
- unique_lock<boost::mutex> l(self->syncher);
58
- vector<Callback> commands = self->commands;
59
- self->commands.clear();
86
+ self->runCommands();
87
+ }
88
+
89
+ static void idleHandler(EV_P_ ev_idle *idle, int revents) {
90
+ SafeLibev *self = (SafeLibev *) idle->data;
91
+ self->runCommands();
92
+ }
93
+
94
+ static void timeoutHandler(EV_P_ ev_timer *t, int revents) {
95
+ auto_ptr<Timer> timer((Timer *) ((const char *) t));
96
+ SafeLibev *self = timer->self;
97
+ self->timers.erase(timer->it);
98
+ ev_timer_stop(self->loop, &timer->realTimer);
99
+ timer->callback();
100
+ }
101
+
102
+ void runCommands() {
103
+ unique_lock<boost::mutex> l(syncher);
104
+ vector<Command> commands = this->commands;
105
+ this->commands.clear();
60
106
  l.unlock();
61
107
 
62
- vector<Callback>::const_iterator it, end = commands.end();
63
- for (it = commands.begin(); it != commands.end(); it++) {
64
- (*it)();
108
+ vector<Command>::const_iterator it, end = commands.end();
109
+ for (it = commands.begin(); it != end; it++) {
110
+ it->callback();
65
111
  }
66
112
  }
67
113
 
@@ -82,23 +128,67 @@ private:
82
128
  cond.notify_all();
83
129
  }
84
130
 
131
+ void runAndNotify(const Callback *callback, bool *done) {
132
+ (*callback)();
133
+ unique_lock<boost::mutex> l(syncher);
134
+ *done = true;
135
+ cond.notify_all();
136
+ }
137
+
138
+ void incNextCommandId() {
139
+ if (nextCommandId == INT_MAX) {
140
+ nextCommandId = 0;
141
+ } else {
142
+ nextCommandId++;
143
+ }
144
+ }
145
+
85
146
  public:
147
+ /** SafeLibev takes over ownership of the loop object. */
86
148
  SafeLibev(struct ev_loop *loop) {
87
149
  this->loop = loop;
88
150
  loopThread = pthread_self();
151
+ nextCommandId = 0;
152
+
89
153
  ev_async_init(&async, asyncHandler);
90
154
  async.data = this;
91
155
  ev_async_start(loop, &async);
156
+
157
+ ev_idle_init(&idle, idleHandler);
158
+ ev_set_priority(&idle, EV_MAXPRI);
159
+ idle.data = this;
92
160
  }
93
161
 
94
162
  ~SafeLibev() {
163
+ destroy();
164
+ ev_loop_destroy(loop);
165
+ }
166
+
167
+ void destroy() {
95
168
  ev_async_stop(loop, &async);
169
+ ev_idle_stop(loop, &idle);
170
+
171
+ list<Timer *>::iterator it, end = timers.end();
172
+ for (it = timers.begin(); it != end; it++) {
173
+ Timer *timer = *it;
174
+ ev_timer_stop(loop, &timer->realTimer);
175
+ delete timer;
176
+ }
177
+ timers.clear();
96
178
  }
97
179
 
98
180
  struct ev_loop *getLoop() const {
99
181
  return loop;
100
182
  }
101
183
 
184
+ void setCurrentThread() {
185
+ loopThread = pthread_self();
186
+ }
187
+
188
+ pthread_t getCurrentThread() const {
189
+ return loopThread;
190
+ }
191
+
102
192
  template<typename Watcher>
103
193
  void start(Watcher &watcher) {
104
194
  if (pthread_equal(pthread_self(), loopThread)) {
@@ -107,8 +197,10 @@ public:
107
197
  } else {
108
198
  unique_lock<boost::mutex> l(syncher);
109
199
  bool done = false;
110
- commands.push_back(boost::bind(&SafeLibev::startWatcherAndNotify<Watcher>,
111
- this, &watcher, &done));
200
+ commands.push_back(Command(nextCommandId,
201
+ boost::bind(&SafeLibev::startWatcherAndNotify<Watcher>,
202
+ this, &watcher, &done)));
203
+ incNextCommandId();
112
204
  ev_async_send(loop, &async);
113
205
  while (!done) {
114
206
  cond.wait(l);
@@ -123,8 +215,10 @@ public:
123
215
  } else {
124
216
  unique_lock<boost::mutex> l(syncher);
125
217
  bool done = false;
126
- commands.push_back(boost::bind(&SafeLibev::stopWatcherAndNotify<Watcher>,
127
- this, &watcher, &done));
218
+ commands.push_back(Command(nextCommandId,
219
+ boost::bind(&SafeLibev::stopWatcherAndNotify<Watcher>,
220
+ this, &watcher, &done)));
221
+ incNextCommandId();
128
222
  ev_async_send(loop, &async);
129
223
  while (!done) {
130
224
  cond.wait(l);
@@ -133,16 +227,94 @@ public:
133
227
  }
134
228
 
135
229
  void run(const Callback &callback) {
230
+ assert(callback != NULL);
136
231
  if (pthread_equal(pthread_self(), loopThread)) {
137
232
  callback();
138
233
  } else {
234
+ runSync(callback);
235
+ }
236
+ }
237
+
238
+ void runSync(const Callback &callback) {
239
+ assert(callback != NULL);
240
+ unique_lock<boost::mutex> l(syncher);
241
+ bool done = false;
242
+ commands.push_back(Command(nextCommandId,
243
+ boost::bind(&SafeLibev::runAndNotify, this,
244
+ &callback, &done)));
245
+ incNextCommandId();
246
+ ev_async_send(loop, &async);
247
+ while (!done) {
248
+ cond.wait(l);
249
+ }
250
+ }
251
+
252
+ void runAsync(const Callback &callback) {
253
+ runLaterTS(callback);
254
+ }
255
+
256
+ // TODO: make it possible to call this from a thread
257
+ void runAfter(unsigned int timeout, const Callback &callback) {
258
+ assert(callback != NULL);
259
+ Timer *timer = new Timer(this, callback);
260
+ ev_timer_init(&timer->realTimer, timeoutHandler, timeout / 1000.0, 0);
261
+ timers.push_front(timer);
262
+ timer->it = timers.begin();
263
+ ev_timer_start(loop, &timer->realTimer);
264
+ }
265
+
266
+ unsigned int runLater(const Callback &callback) {
267
+ assert(callback != NULL);
268
+ unsigned int result;
269
+ {
139
270
  unique_lock<boost::mutex> l(syncher);
140
- commands.push_back(callback);
141
- ev_async_send(loop, &async);
271
+ commands.push_back(Command(nextCommandId, callback));
272
+ result = nextCommandId;
273
+ incNextCommandId();
274
+ }
275
+ if (!ev_is_active(&idle)) {
276
+ ev_idle_start(loop, &idle);
277
+ }
278
+ return result;
279
+ }
280
+
281
+ unsigned int runLaterTS(const Callback &callback) {
282
+ assert(callback != NULL);
283
+ unsigned int result;
284
+ {
285
+ unique_lock<boost::mutex> l(syncher);
286
+ commands.push_back(Command(nextCommandId, callback));
287
+ result = nextCommandId;
288
+ incNextCommandId();
142
289
  }
290
+ ev_async_send(loop, &async);
291
+ return result;
292
+ }
293
+
294
+ /**
295
+ * Cancels a callback that was scheduled to be run by runLater() and runLaterTS().
296
+ * Returns whether the command has been successfully cancelled or not.
297
+ * That is, a return value of true guarantees that the callback will not be called
298
+ * in the future, while a return value of false means that the callback has already
299
+ * been called or is currently being called.
300
+ */
301
+ bool cancelCommand(int id) {
302
+ unique_lock<boost::mutex> l(syncher);
303
+ // TODO: we can do a binary search because the command ID
304
+ // is monotically increasing except on overflow.
305
+ vector<Command>::iterator it, end = commands.end();
306
+ for (it = commands.begin(); it != end; it++) {
307
+ if (it->id == id) {
308
+ commands.erase(it);
309
+ return true;
310
+ }
311
+ }
312
+ return false;
143
313
  }
144
314
  };
145
315
 
316
+ typedef shared_ptr<SafeLibev> SafeLibevPtr;
317
+
146
318
 
147
319
  } // namespace Passenger
148
320
 
@@ -82,10 +82,30 @@ public:
82
82
  /** A hash function object for StaticString. */
83
83
  struct Hash {
84
84
  size_t operator()(const StaticString &str) const {
85
- size_t result = 0;
86
85
  const char *data = str.content;
87
- const char *end = data + str.len;
88
- while (data != end) {
86
+ const char *end = str.content + str.len;
87
+ size_t result = 0;
88
+
89
+ #if defined(__i386__) || defined(__x86_64__)
90
+ /* When on x86 or x86_64, process 4 or 8 bytes
91
+ * per iteration by treating the data as an
92
+ * array of longs. Luckily for us these
93
+ * architectures can read longs even on unaligned
94
+ * addresses.
95
+ */
96
+ const char *last_long = str.content +
97
+ str.len / sizeof(unsigned long) *
98
+ sizeof(unsigned long);
99
+
100
+ while (data < last_long) {
101
+ result = result * 33 + *((unsigned long *) data);
102
+ data += sizeof(unsigned long);
103
+ }
104
+
105
+ /* Process leftover data byte-by-byte. */
106
+ #endif
107
+
108
+ while (data < end) {
89
109
  result = result * 33 + *data;
90
110
  data++;
91
111
  }
@@ -0,0 +1,972 @@
1
+ /*
2
+ * Phusion Passenger - http://www.modrails.com/
3
+ * Copyright (c) 2010, 2011, 2012 Phusion
4
+ *
5
+ * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ */
25
+ #ifndef _PASSENGER_UNION_STATION_H_
26
+ #define _PASSENGER_UNION_STATION_H_
27
+
28
+ #include <boost/shared_ptr.hpp>
29
+ #include <boost/enable_shared_from_this.hpp>
30
+ #include <boost/noncopyable.hpp>
31
+ #include <oxt/thread.hpp>
32
+ #include <oxt/system_calls.hpp>
33
+ #include <oxt/backtrace.hpp>
34
+
35
+ #include <sys/types.h>
36
+ #include <sys/time.h>
37
+ #include <sys/resource.h>
38
+ #include <unistd.h>
39
+ #include <fcntl.h>
40
+ #include <pthread.h>
41
+ #include <string>
42
+ #include <map>
43
+ #include <stdexcept>
44
+ #include <cstdio>
45
+ #include <ctime>
46
+ #include <cerrno>
47
+ #include <cassert>
48
+
49
+ #include <RandomGenerator.h>
50
+ #include <FileDescriptor.h>
51
+ #include <StaticString.h>
52
+ #include <Logging.h>
53
+ #include <Exceptions.h>
54
+ #include <Utils.h>
55
+ #include <Utils/MessageIO.h>
56
+ #include <Utils/StrIntUtils.h>
57
+ #include <Utils/MD5.h>
58
+ #include <Utils/SystemTime.h>
59
+
60
+
61
+ namespace Passenger {
62
+ namespace UnionStation {
63
+
64
+ using namespace std;
65
+ using namespace boost;
66
+ using namespace oxt;
67
+
68
+
69
+ // All access to the file descriptor must be synchronized through the lock.
70
+ struct Connection {
71
+ mutable boost::mutex syncher;
72
+ int fd;
73
+
74
+ Connection(int _fd)
75
+ : fd(_fd)
76
+ { }
77
+
78
+ ~Connection() {
79
+ disconnect();
80
+ }
81
+
82
+ bool connected() const {
83
+ return fd != -1;
84
+ }
85
+
86
+ bool disconnect(string &errorResponse) {
87
+ if (!connected()) {
88
+ return false;
89
+ }
90
+
91
+ /* The server might send an "error" array message
92
+ * just before disconnecting. Try to read it.
93
+ */
94
+ TRACE_POINT();
95
+ vector<string> response;
96
+ try {
97
+ unsigned long long timeout = 20000000;
98
+ while (true) {
99
+ response = readArrayMessage(fd, &timeout);
100
+ }
101
+ } catch (const TimeoutException &) {
102
+ /* This means that the last message isn't an array
103
+ * message or that the server didn't send it quickly
104
+ * enough. In any case, discard whatever previous
105
+ * array messages we were able to read because they're
106
+ * guaranteed not to be the error message we're expecting.
107
+ */
108
+ response.clear();
109
+ } catch (const SystemException &e) {
110
+ /* We treat ECONNRESET the same as EOFException.
111
+ * Other errors are treated as TimeoutException.
112
+ */
113
+ if (e.code() != ECONNRESET) {
114
+ response.clear();
115
+ }
116
+ } catch (const EOFException &) {
117
+ /* Do nothing. We've successfully read the last array message. */
118
+ }
119
+
120
+ UPDATE_TRACE_POINT();
121
+ disconnect();
122
+
123
+ if (response.size() == 2 && response[0] == "error") {
124
+ errorResponse = response[1];
125
+ return true;
126
+ } else {
127
+ return false;
128
+ }
129
+ }
130
+
131
+ void disconnect() {
132
+ if (fd != -1) {
133
+ this_thread::disable_interruption di;
134
+ this_thread::disable_syscall_interruption dsi;
135
+ safelyClose(fd);
136
+ fd = -1;
137
+ }
138
+ }
139
+ };
140
+
141
+ typedef shared_ptr<Connection> ConnectionPtr;
142
+
143
+
144
+ /** A special lock type for Connection that also keeps a smart
145
+ * pointer to the data structure so that the mutex is not destroyed
146
+ * prematurely.
147
+ */
148
+ struct ConnectionLock {
149
+ ConnectionPtr connection;
150
+ bool locked;
151
+
152
+ ConnectionLock(const ConnectionPtr &c)
153
+ : connection(c)
154
+ {
155
+ c->syncher.lock();
156
+ locked = true;
157
+ }
158
+
159
+ ~ConnectionLock() {
160
+ if (locked) {
161
+ connection->syncher.unlock();
162
+ }
163
+ }
164
+
165
+ void reset(const ConnectionPtr &c, bool lockNow = true) {
166
+ if (locked) {
167
+ connection->syncher.unlock();
168
+ }
169
+ connection = c;
170
+ if (lockNow) {
171
+ connection->syncher.lock();
172
+ locked = true;
173
+ } else {
174
+ locked = false;
175
+ }
176
+ }
177
+
178
+ void lock() {
179
+ assert(!locked);
180
+ connection->syncher.lock();
181
+ locked = true;
182
+ }
183
+ };
184
+
185
+
186
+ /**
187
+ * A scope guard which closes the given Connection on destruction unless cleared.
188
+ */
189
+ class ConnectionGuard {
190
+ private:
191
+ ConnectionPtr connection;
192
+ bool cleared;
193
+
194
+ public:
195
+ ConnectionGuard(const ConnectionPtr &_connection)
196
+ : connection(_connection),
197
+ cleared(false)
198
+ { }
199
+
200
+ ~ConnectionGuard() {
201
+ if (!cleared) {
202
+ connection->disconnect();
203
+ }
204
+ }
205
+
206
+ void clear() {
207
+ cleared = true;
208
+ }
209
+ };
210
+
211
+
212
+ enum ExceptionHandlingMode {
213
+ PRINT,
214
+ THROW,
215
+ IGNORE
216
+ };
217
+
218
+
219
+ class LoggerFactory;
220
+ typedef shared_ptr<LoggerFactory> LoggerFactoryPtr;
221
+
222
+ inline void _checkinConnection(const LoggerFactoryPtr &loggerFactory, const ConnectionPtr &connection);
223
+
224
+
225
+ class Logger: public boost::noncopyable {
226
+ private:
227
+ static const int INT64_STR_BUFSIZE = 22; // Long enough for a 64-bit number.
228
+ static const unsigned long long IO_TIMEOUT = 5000000; // In microseconds.
229
+
230
+ const LoggerFactoryPtr loggerFactory;
231
+ const ConnectionPtr connection;
232
+ const string txnId;
233
+ const string groupName;
234
+ const string category;
235
+ const string unionStationKey;
236
+ const ExceptionHandlingMode exceptionHandlingMode;
237
+ bool shouldFlushToDiskAfterClose;
238
+
239
+ /**
240
+ * Buffer must be at least txnId.size() + 1 + INT64_STR_BUFSIZE + 1 bytes.
241
+ */
242
+ char *insertTxnIdAndTimestamp(char *buffer, const char *end) {
243
+ assert(end - buffer >= int(txnId.size() + 1 + INT64_STR_BUFSIZE + 1));
244
+ int size;
245
+
246
+ // "txn-id-here"
247
+ buffer = appendData(buffer, end, txnId);
248
+
249
+ // "txn-id-here "
250
+ buffer = appendData(buffer, end, " ", 1);
251
+
252
+ // "txn-id-here 123456"
253
+ assert(end - buffer >= INT64_STR_BUFSIZE);
254
+ size = snprintf(buffer, INT64_STR_BUFSIZE, "%llu", SystemTime::getUsec());
255
+ if (size >= INT64_STR_BUFSIZE) {
256
+ // The buffer is too small.
257
+ throw IOException("Cannot format a new transaction log message timestamp.");
258
+ }
259
+ buffer += size;
260
+
261
+ // "txn-id-here 123456 "
262
+ buffer = appendData(buffer, end, " ", 1);
263
+
264
+ return buffer;
265
+ }
266
+
267
+ template<typename ExceptionType>
268
+ void handleException(const ExceptionType &e) {
269
+ switch (exceptionHandlingMode) {
270
+ case THROW:
271
+ throw e;
272
+ case PRINT:
273
+ try {
274
+ const tracable_exception &te =
275
+ dynamic_cast<const tracable_exception &>(e);
276
+ P_WARN(te.what() << "\n" << te.backtrace());
277
+ } catch (const bad_cast &) {
278
+ P_WARN(e.what());
279
+ }
280
+ break;
281
+ default:
282
+ break;
283
+ }
284
+ }
285
+
286
+ public:
287
+ Logger()
288
+ : exceptionHandlingMode(PRINT)
289
+ { }
290
+
291
+ Logger(const LoggerFactoryPtr &_loggerFactory,
292
+ const ConnectionPtr &_connection,
293
+ const string &_txnId,
294
+ const string &_groupName,
295
+ const string &_category,
296
+ const string &_unionStationKey,
297
+ ExceptionHandlingMode _exceptionHandlingMode = PRINT)
298
+ : loggerFactory(_loggerFactory),
299
+ connection(_connection),
300
+ txnId(_txnId),
301
+ groupName(_groupName),
302
+ category(_category),
303
+ unionStationKey(_unionStationKey),
304
+ exceptionHandlingMode(_exceptionHandlingMode),
305
+ shouldFlushToDiskAfterClose(false)
306
+ { }
307
+
308
+ ~Logger() {
309
+ TRACE_POINT();
310
+ if (connection == NULL) {
311
+ return;
312
+ }
313
+ ConnectionLock l(connection);
314
+ if (!connection->connected()) {
315
+ return;
316
+ }
317
+
318
+ char timestamp[2 * sizeof(unsigned long long) + 1];
319
+ integerToHexatri<unsigned long long>(SystemTime::getUsec(),
320
+ timestamp);
321
+
322
+ UPDATE_TRACE_POINT();
323
+ ConnectionGuard guard(connection);
324
+ try {
325
+ unsigned long long timeout = IO_TIMEOUT;
326
+ writeArrayMessage(connection->fd, &timeout,
327
+ "closeTransaction",
328
+ txnId.c_str(),
329
+ timestamp,
330
+ NULL);
331
+
332
+ if (shouldFlushToDiskAfterClose) {
333
+ UPDATE_TRACE_POINT();
334
+ timeout = IO_TIMEOUT;
335
+ writeArrayMessage(connection->fd, &timeout,
336
+ "flush", NULL);
337
+ readArrayMessage(connection->fd, &timeout);
338
+ }
339
+
340
+ _checkinConnection(loggerFactory, connection);
341
+ guard.clear();
342
+ } catch (const SystemException &e) {
343
+ string errorResponse;
344
+
345
+ UPDATE_TRACE_POINT();
346
+ guard.clear();
347
+ if (connection->disconnect(errorResponse)) {
348
+ handleException(IOException(
349
+ "Logging agent disconnected with error: " +
350
+ errorResponse));
351
+ } else {
352
+ handleException(e);
353
+ }
354
+ }
355
+ }
356
+
357
+ void message(const StaticString &text) {
358
+ TRACE_POINT();
359
+ if (connection == NULL) {
360
+ P_TRACE(3, "[Union Station log to null] " << text);
361
+ return;
362
+ }
363
+ ConnectionLock l(connection);
364
+ if (!connection->connected()) {
365
+ P_TRACE(3, "[Union Station log to null] " << text);
366
+ return;
367
+ }
368
+
369
+ char timestamp[2 * sizeof(unsigned long long) + 1];
370
+ integerToHexatri<unsigned long long>(SystemTime::getUsec(), timestamp);
371
+
372
+ UPDATE_TRACE_POINT();
373
+ ConnectionGuard guard(connection);
374
+ try {
375
+ unsigned long long timeout = IO_TIMEOUT;
376
+ P_TRACE(3, "[Union Station log] " << txnId << " " << timestamp << " " << text);
377
+ writeArrayMessage(connection->fd, &timeout,
378
+ "log",
379
+ txnId.c_str(),
380
+ timestamp,
381
+ NULL);
382
+ writeScalarMessage(connection->fd, text, &timeout);
383
+ guard.clear();
384
+ } catch (const std::exception &e) {
385
+ string errorResponse;
386
+
387
+ UPDATE_TRACE_POINT();
388
+ guard.clear();
389
+ if (connection->disconnect(errorResponse)) {
390
+ handleException(IOException(
391
+ "Logging agent disconnected with error: " +
392
+ errorResponse));
393
+ } else {
394
+ handleException(e);
395
+ }
396
+ }
397
+ }
398
+
399
+ void abort(const StaticString &text) {
400
+ message("ABORT");
401
+ }
402
+
403
+ void flushToDiskAfterClose(bool value) {
404
+ shouldFlushToDiskAfterClose = value;
405
+ }
406
+
407
+ bool isNull() const {
408
+ return connection == NULL;
409
+ }
410
+
411
+ const string &getTxnId() const {
412
+ return txnId;
413
+ }
414
+
415
+ const string &getGroupName() const {
416
+ return groupName;
417
+ }
418
+
419
+ const string &getCategory() const {
420
+ return category;
421
+ }
422
+
423
+ const string &getUnionStationKey() const {
424
+ return unionStationKey;
425
+ }
426
+ };
427
+
428
+ typedef shared_ptr<Logger> LoggerPtr;
429
+
430
+
431
+ class ScopeLog: public noncopyable {
432
+ private:
433
+ Logger * const log;
434
+ enum {
435
+ NAME,
436
+ GRANULAR
437
+ } type;
438
+ union {
439
+ const char *name;
440
+ struct {
441
+ const char *endMessage;
442
+ const char *abortMessage;
443
+ } granular;
444
+ } data;
445
+ bool ok;
446
+
447
+ static string timevalToString(struct timeval &tv) {
448
+ unsigned long long i = (unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec;
449
+ return usecToString(i);
450
+ }
451
+
452
+ static string usecToString(unsigned long long usec) {
453
+ char timestamp[2 * sizeof(unsigned long long) + 1];
454
+ integerToHexatri<unsigned long long>(usec, timestamp);
455
+ return timestamp;
456
+ }
457
+
458
+ public:
459
+ ScopeLog()
460
+ : log(NULL)
461
+ { }
462
+
463
+ ScopeLog(const LoggerPtr &_log, const char *name)
464
+ : log(_log.get())
465
+ {
466
+ type = NAME;
467
+ data.name = name;
468
+ ok = false;
469
+
470
+ char message[150];
471
+ char *pos = message;
472
+ const char *end = message + sizeof(message);
473
+ struct rusage usage;
474
+
475
+ pos = appendData(pos, end, "BEGIN: ");
476
+ pos = appendData(pos, end, name);
477
+ pos = appendData(pos, end, " (");
478
+ pos = appendData(pos, end, usecToString(SystemTime::getUsec()));
479
+ pos = appendData(pos, end, ",");
480
+ if (getrusage(RUSAGE_SELF, &usage) == -1) {
481
+ int e = errno;
482
+ throw SystemException("getrusage() failed", e);
483
+ }
484
+ pos = appendData(pos, end, timevalToString(usage.ru_utime));
485
+ pos = appendData(pos, end, ",");
486
+ pos = appendData(pos, end, timevalToString(usage.ru_stime));
487
+ pos = appendData(pos, end, ") ");
488
+
489
+ if (log != NULL) {
490
+ log->message(StaticString(message, pos - message));
491
+ }
492
+ }
493
+
494
+ ScopeLog(const LoggerPtr &_log,
495
+ const char *beginMessage,
496
+ const char *endMessage,
497
+ const char *abortMessage = NULL)
498
+ : log(_log.get())
499
+ {
500
+ if (_log != NULL) {
501
+ type = GRANULAR;
502
+ data.granular.endMessage = endMessage;
503
+ data.granular.abortMessage = abortMessage;
504
+ ok = abortMessage == NULL;
505
+ _log->message(beginMessage);
506
+ }
507
+ }
508
+
509
+ ~ScopeLog() {
510
+ if (log == NULL) {
511
+ return;
512
+ }
513
+ if (type == NAME) {
514
+ char message[150];
515
+ char *pos = message;
516
+ const char *end = message + sizeof(message);
517
+ struct rusage usage;
518
+
519
+ if (ok) {
520
+ pos = appendData(pos, end, "END: ");
521
+ } else {
522
+ pos = appendData(pos, end, "FAIL: ");
523
+ }
524
+ pos = appendData(pos, end, data.name);
525
+ pos = appendData(pos, end, " (");
526
+ pos = appendData(pos, end, usecToString(SystemTime::getUsec()));
527
+ pos = appendData(pos, end, ",");
528
+ if (getrusage(RUSAGE_SELF, &usage) == -1) {
529
+ int e = errno;
530
+ throw SystemException("getrusage() failed", e);
531
+ }
532
+ pos = appendData(pos, end, timevalToString(usage.ru_utime));
533
+ pos = appendData(pos, end, ",");
534
+ pos = appendData(pos, end, timevalToString(usage.ru_stime));
535
+ pos = appendData(pos, end, ")");
536
+
537
+ log->message(StaticString(message, pos - message));
538
+ } else {
539
+ if (ok) {
540
+ log->message(data.granular.endMessage);
541
+ } else {
542
+ log->message(data.granular.abortMessage);
543
+ }
544
+ }
545
+ }
546
+
547
+ void success() {
548
+ ok = true;
549
+ }
550
+ };
551
+
552
+
553
+ class LoggerFactory: public enable_shared_from_this<LoggerFactory> {
554
+ private:
555
+ static const unsigned int CONNECTION_POOL_MAX_SIZE = 10;
556
+
557
+ const string serverAddress;
558
+ const string username;
559
+ const string password;
560
+ const string nodeName;
561
+ RandomGenerator randomGenerator;
562
+
563
+ LoggerPtr nullLogger;
564
+
565
+ /** Lock protecting the fields that follow, but not the
566
+ * contents of the connection object.
567
+ */
568
+ mutable boost::mutex syncher;
569
+ vector<ConnectionPtr> connectionPool;
570
+ unsigned int maxConnectTries;
571
+ unsigned long long reconnectTimeout;
572
+ unsigned long long nextReconnectTime;
573
+
574
+ static string determineNodeName(const string &givenNodeName) {
575
+ if (givenNodeName.empty()) {
576
+ return getHostName();
577
+ } else {
578
+ return givenNodeName;
579
+ }
580
+ }
581
+
582
+ static bool isNetworkError(int code) {
583
+ return code == EPIPE || code == ECONNREFUSED || code == ECONNRESET
584
+ || code == EHOSTUNREACH || code == ENETDOWN || code == ENETUNREACH
585
+ || code == ETIMEDOUT;
586
+ }
587
+
588
+ template<typename T>
589
+ static bool instanceof(const std::exception &e) {
590
+ try {
591
+ (void) dynamic_cast<const T &>(e);
592
+ return true;
593
+ } catch (const bad_cast &) {
594
+ return false;
595
+ }
596
+ }
597
+
598
+ ConnectionPtr createNewConnection() {
599
+ TRACE_POINT();
600
+ int fd;
601
+ vector<string> args;
602
+ unsigned long long timeout = 15000000;
603
+
604
+ fd = connectToServer(serverAddress);
605
+ FdGuard guard(fd, true);
606
+ if (!readArrayMessage(fd, args, &timeout)) {
607
+ throw IOException("The logging agent closed the connection before sending a version identifier.");
608
+ }
609
+ if (args.size() != 2 || args[0] != "version") {
610
+ throw IOException("The logging agent server didn't sent a valid version identifier.");
611
+ }
612
+ if (args[1] != "1") {
613
+ string message = "Unsupported logging agent protocol version " +
614
+ args[1] + ".";
615
+ throw IOException(message);
616
+ }
617
+
618
+ UPDATE_TRACE_POINT();
619
+ writeScalarMessage(fd, username, &timeout);
620
+ writeScalarMessage(fd, password, &timeout);
621
+
622
+ UPDATE_TRACE_POINT();
623
+ if (!readArrayMessage(fd, args, &timeout)) {
624
+ throw IOException("The logging agent did not send an authentication response.");
625
+ } else if (args.size() != 1) {
626
+ throw IOException("The authentication response that the logging agent sent is not valid.");
627
+ } else if (args[0] != "ok") {
628
+ throw SecurityException("The logging agent server denied authentication: " + args[0]);
629
+ }
630
+
631
+ UPDATE_TRACE_POINT();
632
+ writeArrayMessage(fd, &timeout, "init", nodeName.c_str(), NULL);
633
+ if (!readArrayMessage(fd, args, &timeout)) {
634
+ throw SystemException("Cannot connect to logging server", ECONNREFUSED);
635
+ } else if (args.size() != 1) {
636
+ throw IOException("Logging server returned an invalid reply for the 'init' command");
637
+ } else if (args[0] == "server shutting down") {
638
+ throw SystemException("Cannot connect to server", ECONNREFUSED);
639
+ } else if (args[0] != "ok") {
640
+ throw IOException("Logging server returned an invalid reply for the 'init' command");
641
+ }
642
+
643
+ guard.clear();
644
+ return make_shared<Connection>(fd);
645
+ }
646
+
647
+ public:
648
+ LoggerFactory() {
649
+ nullLogger = make_shared<Logger>();
650
+ }
651
+
652
+ LoggerFactory(const string &_serverAddress, const string &_username,
653
+ const string &_password, const string &_nodeName = string())
654
+ : serverAddress(_serverAddress),
655
+ username(_username),
656
+ password(_password),
657
+ nodeName(determineNodeName(_nodeName))
658
+ {
659
+ nullLogger = make_shared<Logger>();
660
+ if (!_serverAddress.empty() && isLocalSocketAddress(_serverAddress)) {
661
+ maxConnectTries = 10;
662
+ } else {
663
+ maxConnectTries = 1;
664
+ }
665
+ reconnectTimeout = 1000000;
666
+ nextReconnectTime = 0;
667
+ }
668
+
669
+ ConnectionPtr checkoutConnection() {
670
+ TRACE_POINT();
671
+ unique_lock<boost::mutex> l(syncher);
672
+ if (!connectionPool.empty()) {
673
+ P_TRACE(3, "Checked out existing connection");
674
+ ConnectionPtr connection = connectionPool.back();
675
+ connectionPool.pop_back();
676
+ return connection;
677
+
678
+ } else {
679
+ if (SystemTime::getUsec() < nextReconnectTime) {
680
+ P_TRACE(3, "Not yet time to reconnect; returning NULL connection");
681
+ return ConnectionPtr();
682
+ }
683
+
684
+ l.unlock();
685
+ P_TRACE(3, "Creating new connection with logging agent");
686
+ ConnectionPtr connection;
687
+ try {
688
+ connection = createNewConnection();
689
+ } catch (const TimeoutException &) {
690
+ l.lock();
691
+ P_WARN("Timeout trying to connect to the logging agent at " << serverAddress << "; " <<
692
+ "will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
693
+ nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
694
+ return ConnectionPtr();
695
+ } catch (const tracable_exception &e) {
696
+ l.lock();
697
+ nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
698
+ if (instanceof<IOException>(e) || instanceof<SystemException>(e)) {
699
+ P_WARN("Cannot connect to the logging agent at " << serverAddress <<
700
+ " (" << e.what() << "); will reconnect in " <<
701
+ reconnectTimeout / 1000000 << " second(s).");
702
+ return ConnectionPtr();
703
+ } else {
704
+ throw;
705
+ }
706
+ }
707
+
708
+ return connection;
709
+ }
710
+ }
711
+
712
+ void checkinConnection(const ConnectionPtr &connection) {
713
+ lock_guard<boost::mutex> l(syncher);
714
+ if (connectionPool.size() < CONNECTION_POOL_MAX_SIZE) {
715
+ connectionPool.push_back(connection);
716
+ } else {
717
+ connection->disconnect();
718
+ }
719
+ }
720
+
721
+ LoggerPtr createNullLogger() const {
722
+ return nullLogger;
723
+ }
724
+
725
+ LoggerPtr newTransaction(const string &groupName,
726
+ const string &category = "requests",
727
+ const string &unionStationKey = string(),
728
+ const string &filters = string())
729
+ {
730
+ if (serverAddress.empty()) {
731
+ return createNullLogger();
732
+ }
733
+
734
+ unsigned long long timestamp = SystemTime::getUsec();
735
+ char txnId[
736
+ 2 * sizeof(unsigned int) + // max hex timestamp size
737
+ 11 + // space for a random identifier
738
+ 1 // null terminator
739
+ ];
740
+ char *end;
741
+ unsigned int timestampSize;
742
+ char timestampStr[2 * sizeof(unsigned long long) + 1];
743
+
744
+ // "[timestamp]"
745
+ // Our timestamp is like a Unix timestamp but with minutes
746
+ // resolution instead of seconds. 32 bits will last us for
747
+ // about 8000 years.
748
+ timestampSize = integerToHexatri<unsigned int>(timestamp / 1000000 / 60,
749
+ txnId);
750
+ end = txnId + timestampSize;
751
+
752
+ // "[timestamp]-"
753
+ *end = '-';
754
+ end++;
755
+
756
+ // "[timestamp]-[random id]"
757
+ randomGenerator.generateAsciiString(end, 11);
758
+ end += 11;
759
+ *end = '\0';
760
+
761
+ integerToHexatri<unsigned long long>(timestamp, timestampStr);
762
+
763
+ ConnectionPtr connection = checkoutConnection();
764
+ if (connection == NULL) {
765
+ return createNullLogger();
766
+ }
767
+
768
+ ConnectionLock cl(connection);
769
+ ConnectionGuard guard(connection);
770
+
771
+ try {
772
+ unsigned long long timeout = 15000000;
773
+
774
+ writeArrayMessage(connection->fd, &timeout,
775
+ "openTransaction",
776
+ txnId,
777
+ groupName.c_str(),
778
+ "",
779
+ category.c_str(),
780
+ timestampStr,
781
+ unionStationKey.c_str(),
782
+ "true",
783
+ "true",
784
+ filters.c_str(),
785
+ NULL);
786
+
787
+ vector<string> args;
788
+ if (!readArrayMessage(connection->fd, args, &timeout)) {
789
+ lock_guard<boost::mutex> l(syncher);
790
+ P_WARN("The logging agent at " << serverAddress <<
791
+ " closed the connection (no error message given);" <<
792
+ " will reconnect in " << reconnectTimeout / 1000000 <<
793
+ " second(s).");
794
+ nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
795
+ return createNullLogger();
796
+ } else if (args.size() == 2 && args[0] == "error") {
797
+ lock_guard<boost::mutex> l(syncher);
798
+ P_WARN("The logging agent at " << serverAddress <<
799
+ " closed the connection (error message: " << args[1] <<
800
+ "); will reconnect in " << reconnectTimeout / 1000000 <<
801
+ " second(s).");
802
+ nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
803
+ return createNullLogger();
804
+ } else if (args.empty() || args[0] != "ok") {
805
+ lock_guard<boost::mutex> l(syncher);
806
+ P_WARN("The logging agent at " << serverAddress <<
807
+ " sent an unexpected reply;" <<
808
+ " will reconnect in " << reconnectTimeout / 1000000 <<
809
+ " second(s).");
810
+ nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
811
+ return createNullLogger();
812
+ }
813
+
814
+ guard.clear();
815
+ return make_shared<Logger>(shared_from_this(),
816
+ connection,
817
+ string(txnId, end - txnId),
818
+ groupName, category,
819
+ unionStationKey);
820
+
821
+ } catch (const TimeoutException &) {
822
+ lock_guard<boost::mutex> l(syncher);
823
+ P_WARN("Timeout trying to communicate with the logging agent at " << serverAddress << "; " <<
824
+ "will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
825
+ nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
826
+ return createNullLogger();
827
+
828
+ } catch (const SystemException &e) {
829
+ if (e.code() == ENOENT || isNetworkError(e.code())) {
830
+ string errorResponse;
831
+ bool gotErrorResponse;
832
+
833
+ guard.clear();
834
+ gotErrorResponse = connection->disconnect(errorResponse);
835
+ lock_guard<boost::mutex> l(syncher);
836
+ if (gotErrorResponse) {
837
+ P_WARN("The logging agent at " << serverAddress <<
838
+ " closed the connection (error message: " << errorResponse <<
839
+ "); will reconnect in " << reconnectTimeout / 1000000 <<
840
+ " second(s).");
841
+ } else {
842
+ P_WARN("The logging agent at " << serverAddress <<
843
+ " closed the connection (no error message given);" <<
844
+ " will reconnect in " << reconnectTimeout / 1000000 <<
845
+ " second(s).");
846
+ }
847
+ nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
848
+ return createNullLogger();
849
+ } else {
850
+ throw;
851
+ }
852
+ }
853
+ }
854
+
855
+ LoggerPtr continueTransaction(const string &txnId,
856
+ const string &groupName,
857
+ const string &category = "requests",
858
+ const string &unionStationKey = string())
859
+ {
860
+ if (serverAddress.empty() || txnId.empty()) {
861
+ return createNullLogger();
862
+ }
863
+
864
+ char timestampStr[2 * sizeof(unsigned long long) + 1];
865
+ integerToHexatri<unsigned long long>(SystemTime::getUsec(), timestampStr);
866
+
867
+ ConnectionPtr connection = checkoutConnection();
868
+ if (connection == NULL) {
869
+ return createNullLogger();
870
+ }
871
+
872
+ ConnectionLock cl(connection);
873
+ ConnectionGuard guard(connection);
874
+
875
+ try {
876
+ unsigned long long timeout = 15000000;
877
+ writeArrayMessage(connection->fd, &timeout,
878
+ "openTransaction",
879
+ txnId.c_str(),
880
+ groupName.c_str(),
881
+ "",
882
+ category.c_str(),
883
+ timestampStr,
884
+ unionStationKey.c_str(),
885
+ "true",
886
+ NULL);
887
+ guard.clear();
888
+ return make_shared<Logger>(shared_from_this(),
889
+ connection,
890
+ txnId, groupName, category,
891
+ unionStationKey);
892
+
893
+ } catch (const TimeoutException &) {
894
+ lock_guard<boost::mutex> l(syncher);
895
+ P_WARN("Timeout trying to communicate with the logging agent at " << serverAddress << "; " <<
896
+ "will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
897
+ nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
898
+ return createNullLogger();
899
+
900
+ } catch (const SystemException &e) {
901
+ if (e.code() == ENOENT || isNetworkError(e.code())) {
902
+ string errorResponse;
903
+ bool gotErrorResponse;
904
+
905
+ guard.clear();
906
+ gotErrorResponse = connection->disconnect(errorResponse);
907
+ lock_guard<boost::mutex> l(syncher);
908
+ if (gotErrorResponse) {
909
+ P_WARN("The logging agent at " << serverAddress <<
910
+ " closed the connection (error message: " << errorResponse <<
911
+ "); will reconnect in " << reconnectTimeout / 1000000 <<
912
+ " second(s).");
913
+ } else {
914
+ P_WARN("The logging agent at " << serverAddress <<
915
+ " closed the connection (no error message given);" <<
916
+ " will reconnect in " << reconnectTimeout / 1000000 <<
917
+ " second(s).");
918
+ }
919
+ nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
920
+ return createNullLogger();
921
+ } else {
922
+ throw;
923
+ }
924
+ }
925
+ }
926
+
927
+ void setMaxConnectTries(unsigned int value) {
928
+ lock_guard<boost::mutex> l(syncher);
929
+ maxConnectTries = value;
930
+ }
931
+
932
+ void setReconnectTimeout(unsigned long long usec) {
933
+ lock_guard<boost::mutex> l(syncher);
934
+ reconnectTimeout = usec;
935
+ }
936
+
937
+ bool isNull() const {
938
+ return serverAddress.empty();
939
+ }
940
+
941
+ const string &getAddress() const {
942
+ return serverAddress;
943
+ }
944
+
945
+ const string &getUsername() const {
946
+ return username;
947
+ }
948
+
949
+ const string &getPassword() const {
950
+ return password;
951
+ }
952
+
953
+ /**
954
+ * @post !result.empty()
955
+ */
956
+ const string &getNodeName() const {
957
+ return nodeName;
958
+ }
959
+ };
960
+
961
+
962
+ inline void
963
+ _checkinConnection(const LoggerFactoryPtr &loggerFactory, const ConnectionPtr &connection) {
964
+ loggerFactory->checkinConnection(connection);
965
+ }
966
+
967
+
968
+ } // namespace UnionStation
969
+ } // namespace Passenger
970
+
971
+ #endif /* _PASSENGER_UNION_STATION_H_ */
972
+