passenger 3.0.0 → 3.0.1

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 (538) hide show
  1. data/DEVELOPERS.TXT +9 -6
  2. data/NEWS +50 -0
  3. data/Rakefile +2 -1
  4. data/bin/passenger-install-apache2-module +4 -4
  5. data/bin/passenger-install-nginx-module +1 -1
  6. data/bin/passenger-make-enterprisey +1 -1
  7. data/build/agents.rb +26 -19
  8. data/build/apache2.rb +49 -46
  9. data/build/basics.rb +37 -13
  10. data/build/common_library.rb +134 -64
  11. data/build/config.rb +18 -11
  12. data/build/cplusplus_support.rb +4 -0
  13. data/build/cxx_tests.rb +26 -12
  14. data/build/documentation.rb +18 -11
  15. data/build/integration_tests.rb +18 -11
  16. data/build/misc.rb +18 -11
  17. data/build/nginx.rb +27 -19
  18. data/build/oxt_tests.rb +18 -11
  19. data/build/packaging.rb +45 -37
  20. data/build/rpm.rb +98 -0
  21. data/build/ruby_extension.rb +19 -13
  22. data/build/ruby_tests.rb +19 -12
  23. data/build/test_basics.rb +23 -11
  24. data/debian/README.Debian +15 -0
  25. data/debian/changelog +185 -0
  26. data/debian/control +47 -19
  27. data/debian/copyright +20 -0
  28. data/debian/libapache2-mod-passenger.install +1 -0
  29. data/debian/libapache2-mod-passenger.postinst +36 -0
  30. data/debian/libapache2-mod-passenger.prerm +15 -0
  31. data/debian/passenger-common.install +4 -0
  32. data/debian/passenger.conf +4 -0
  33. data/debian/passenger.load +1 -0
  34. data/debian/rules +37 -0
  35. data/debian/watch +3 -0
  36. data/{misc → dev}/copy_boost_headers.rb +3 -0
  37. data/{misc → dev}/find_owner_pipe_leaks.rb +0 -0
  38. data/{misc → dev}/render_error_pages.rb +0 -0
  39. data/doc/Users guide Apache.html +39 -1
  40. data/doc/Users guide Apache.txt +40 -0
  41. data/doc/Users guide Nginx.html +1 -1
  42. data/doc/Users guide Standalone.html +1 -1
  43. data/doc/cxxapi/Constants_8h_source.html +1 -1
  44. data/doc/cxxapi/DirectoryMapper_8h_source.html +6 -22
  45. data/doc/cxxapi/EventedClient_8h_source.html +572 -468
  46. data/doc/cxxapi/Exceptions_8h_source.html +142 -129
  47. data/doc/cxxapi/FileDescriptor_8h_source.html +263 -199
  48. data/doc/cxxapi/MessageChannel_8h_source.html +686 -770
  49. data/doc/cxxapi/MessageServer_8h_source.html +1 -1
  50. data/doc/cxxapi/PoolOptions_8h_source.html +79 -78
  51. data/doc/cxxapi/ResourceLocator_8h_source.html +105 -55
  52. data/doc/cxxapi/SafeLibev_8h_source.html +180 -0
  53. data/doc/cxxapi/ServerInstanceDir_8h_source.html +114 -110
  54. data/doc/cxxapi/Session_8h_source.html +1 -1
  55. data/doc/cxxapi/SpawnManager_8h_source.html +208 -208
  56. data/doc/cxxapi/StaticString_8h_source.html +258 -183
  57. data/doc/cxxapi/Utils_8h_source.html +71 -54
  58. data/doc/cxxapi/annotated.html +3 -0
  59. data/doc/cxxapi/classAgentWatcher.html +2 -2
  60. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +0 -1
  61. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +0 -27
  62. data/doc/cxxapi/classPassenger_1_1EventedClient-members.html +5 -0
  63. data/doc/cxxapi/classPassenger_1_1EventedClient.html +102 -7
  64. data/doc/cxxapi/classPassenger_1_1FileDescriptor-members.html +2 -1
  65. data/doc/cxxapi/classPassenger_1_1FileDescriptor.html +34 -8
  66. data/doc/cxxapi/classPassenger_1_1FileDescriptorPair-members.html +36 -0
  67. data/doc/cxxapi/classPassenger_1_1FileDescriptorPair.html +52 -0
  68. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +0 -3
  69. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +0 -120
  70. data/doc/cxxapi/classPassenger_1_1SafeLibev-members.html +36 -0
  71. data/doc/cxxapi/classPassenger_1_1SafeLibev.html +51 -0
  72. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +1 -0
  73. data/doc/cxxapi/classPassenger_1_1SpawnException.html +22 -0
  74. data/doc/cxxapi/classes.html +14 -14
  75. data/doc/cxxapi/files.html +2 -0
  76. data/doc/cxxapi/functions_0x63.html +6 -3
  77. data/doc/cxxapi/functions_0x64.html +9 -2
  78. data/doc/cxxapi/functions_0x67.html +6 -9
  79. data/doc/cxxapi/functions_0x69.html +3 -0
  80. data/doc/cxxapi/functions_0x77.html +8 -8
  81. data/doc/cxxapi/functions_eval.html +6 -0
  82. data/doc/cxxapi/functions_func.html +18 -17
  83. data/doc/cxxapi/functions_vars.html +8 -0
  84. data/doc/cxxapi/graph_legend.png +0 -0
  85. data/doc/cxxapi/group__Core.png +0 -0
  86. data/doc/cxxapi/group__Hooks.png +0 -0
  87. data/doc/cxxapi/hierarchy.html +3 -0
  88. data/doc/cxxapi/inherit__graph__14.map +1 -1
  89. data/doc/cxxapi/inherit__graph__14.md5 +1 -1
  90. data/doc/cxxapi/inherit__graph__14.png +0 -0
  91. data/doc/cxxapi/inherit__graph__15.map +1 -3
  92. data/doc/cxxapi/inherit__graph__15.md5 +1 -1
  93. data/doc/cxxapi/inherit__graph__15.png +0 -0
  94. data/doc/cxxapi/inherit__graph__16.map +3 -1
  95. data/doc/cxxapi/inherit__graph__16.md5 +1 -1
  96. data/doc/cxxapi/inherit__graph__16.png +0 -0
  97. data/doc/cxxapi/inherit__graph__17.map +1 -1
  98. data/doc/cxxapi/inherit__graph__17.md5 +1 -1
  99. data/doc/cxxapi/inherit__graph__17.png +0 -0
  100. data/doc/cxxapi/inherit__graph__18.map +1 -2
  101. data/doc/cxxapi/inherit__graph__18.md5 +1 -1
  102. data/doc/cxxapi/inherit__graph__18.png +0 -0
  103. data/doc/cxxapi/inherit__graph__19.map +2 -1
  104. data/doc/cxxapi/inherit__graph__19.md5 +1 -1
  105. data/doc/cxxapi/inherit__graph__19.png +0 -0
  106. data/doc/cxxapi/inherit__graph__20.map +1 -1
  107. data/doc/cxxapi/inherit__graph__20.md5 +1 -1
  108. data/doc/cxxapi/inherit__graph__20.png +0 -0
  109. data/doc/cxxapi/inherit__graph__21.map +1 -1
  110. data/doc/cxxapi/inherit__graph__21.md5 +1 -1
  111. data/doc/cxxapi/inherit__graph__21.png +0 -0
  112. data/doc/cxxapi/inherit__graph__22.map +1 -1
  113. data/doc/cxxapi/inherit__graph__22.md5 +1 -1
  114. data/doc/cxxapi/inherit__graph__22.png +0 -0
  115. data/doc/cxxapi/inherit__graph__23.map +1 -1
  116. data/doc/cxxapi/inherit__graph__23.md5 +1 -1
  117. data/doc/cxxapi/inherit__graph__23.png +0 -0
  118. data/doc/cxxapi/inherit__graph__24.map +1 -1
  119. data/doc/cxxapi/inherit__graph__24.md5 +1 -1
  120. data/doc/cxxapi/inherit__graph__24.png +0 -0
  121. data/doc/cxxapi/inherit__graph__25.map +1 -1
  122. data/doc/cxxapi/inherit__graph__25.md5 +1 -1
  123. data/doc/cxxapi/inherit__graph__25.png +0 -0
  124. data/doc/cxxapi/inherit__graph__26.map +1 -1
  125. data/doc/cxxapi/inherit__graph__26.md5 +1 -1
  126. data/doc/cxxapi/inherit__graph__26.png +0 -0
  127. data/doc/cxxapi/inherit__graph__27.map +1 -1
  128. data/doc/cxxapi/inherit__graph__27.md5 +1 -1
  129. data/doc/cxxapi/inherit__graph__27.png +0 -0
  130. data/doc/cxxapi/inherit__graph__28.map +1 -2
  131. data/doc/cxxapi/inherit__graph__28.md5 +1 -1
  132. data/doc/cxxapi/inherit__graph__28.png +0 -0
  133. data/doc/cxxapi/inherit__graph__29.map +1 -1
  134. data/doc/cxxapi/inherit__graph__29.md5 +1 -1
  135. data/doc/cxxapi/inherit__graph__29.png +0 -0
  136. data/doc/cxxapi/inherit__graph__30.map +1 -1
  137. data/doc/cxxapi/inherit__graph__30.md5 +1 -1
  138. data/doc/cxxapi/inherit__graph__30.png +0 -0
  139. data/doc/cxxapi/inherit__graph__31.map +2 -1
  140. data/doc/cxxapi/inherit__graph__31.md5 +1 -1
  141. data/doc/cxxapi/inherit__graph__31.png +0 -0
  142. data/doc/cxxapi/inherit__graph__32.map +1 -3
  143. data/doc/cxxapi/inherit__graph__32.md5 +1 -1
  144. data/doc/cxxapi/inherit__graph__32.png +0 -0
  145. data/doc/cxxapi/inherit__graph__33.map +1 -1
  146. data/doc/cxxapi/inherit__graph__33.md5 +1 -1
  147. data/doc/cxxapi/inherit__graph__33.png +0 -0
  148. data/doc/cxxapi/inherit__graph__34.map +1 -1
  149. data/doc/cxxapi/inherit__graph__34.md5 +1 -1
  150. data/doc/cxxapi/inherit__graph__34.png +0 -0
  151. data/doc/cxxapi/inherit__graph__35.map +3 -1
  152. data/doc/cxxapi/inherit__graph__35.md5 +1 -1
  153. data/doc/cxxapi/inherit__graph__35.png +0 -0
  154. data/doc/cxxapi/inherit__graph__36.map +1 -1
  155. data/doc/cxxapi/inherit__graph__36.md5 +1 -1
  156. data/doc/cxxapi/inherit__graph__36.png +0 -0
  157. data/doc/cxxapi/inherit__graph__37.map +1 -1
  158. data/doc/cxxapi/inherit__graph__37.md5 +1 -1
  159. data/doc/cxxapi/inherit__graph__37.png +0 -0
  160. data/doc/cxxapi/inherit__graph__38.map +3 -1
  161. data/doc/cxxapi/inherit__graph__38.md5 +1 -1
  162. data/doc/cxxapi/inherit__graph__38.png +0 -0
  163. data/doc/cxxapi/inherit__graph__39.map +3 -1
  164. data/doc/cxxapi/inherit__graph__39.md5 +1 -1
  165. data/doc/cxxapi/inherit__graph__39.png +0 -0
  166. data/doc/cxxapi/inherits.html +33 -24
  167. data/doc/cxxapi/namespacePassenger.html +52 -0
  168. data/doc/cxxapi/namespacemembers.html +6 -0
  169. data/doc/cxxapi/namespacemembers_func.html +6 -0
  170. data/doc/cxxapi/tree.html +8 -0
  171. data/ext/apache2/Configuration.cpp +30 -8
  172. data/ext/apache2/Configuration.hpp +15 -14
  173. data/ext/apache2/DirectoryMapper.h +0 -16
  174. data/ext/apache2/Hooks.cpp +30 -29
  175. data/ext/boost/algorithm/string/detail/case_conv.hpp +6 -6
  176. data/ext/boost/algorithm/string/detail/find_format.hpp +14 -4
  177. data/ext/boost/algorithm/string/detail/find_format_all.hpp +13 -3
  178. data/ext/boost/algorithm/string/detail/find_format_store.hpp +11 -0
  179. data/ext/boost/algorithm/string/erase.hpp +2 -2
  180. data/ext/boost/bind/placeholders.hpp +2 -2
  181. data/ext/boost/concept/detail/backward_compatibility.hpp +16 -0
  182. data/ext/boost/concept/detail/general.hpp +15 -6
  183. data/ext/boost/concept/detail/has_constraints.hpp +5 -3
  184. data/ext/boost/concept/usage.hpp +5 -4
  185. data/ext/boost/concept_check.hpp +10 -1
  186. data/ext/boost/config/abi/borland_prefix.hpp +1 -1
  187. data/ext/boost/config/auto_link.hpp +68 -21
  188. data/ext/boost/config/compiler/borland.hpp +11 -3
  189. data/ext/boost/config/compiler/clang.hpp +62 -0
  190. data/ext/boost/config/compiler/codegear.hpp +21 -7
  191. data/ext/boost/config/compiler/common_edg.hpp +4 -2
  192. data/ext/boost/config/compiler/digitalmars.hpp +1 -1
  193. data/ext/boost/config/compiler/gcc.hpp +46 -7
  194. data/ext/boost/config/compiler/gcc_xml.hpp +25 -0
  195. data/ext/boost/config/compiler/intel.hpp +23 -0
  196. data/ext/boost/config/compiler/kai.hpp +1 -1
  197. data/ext/boost/config/compiler/metrowerks.hpp +1 -1
  198. data/ext/boost/config/compiler/nvcc.hpp +86 -0
  199. data/ext/boost/config/compiler/pgi.hpp +18 -3
  200. data/ext/boost/config/compiler/sunpro_cc.hpp +19 -5
  201. data/ext/boost/config/compiler/vacpp.hpp +8 -0
  202. data/ext/boost/config/compiler/visualc.hpp +27 -11
  203. data/ext/boost/config/platform/cygwin.hpp +0 -3
  204. data/ext/boost/config/platform/symbian.hpp +94 -0
  205. data/ext/boost/config/platform/win32.hpp +8 -1
  206. data/ext/boost/config/select_compiler_config.hpp +10 -0
  207. data/ext/boost/config/select_platform_config.hpp +4 -0
  208. data/ext/boost/config/stdlib/dinkumware.hpp +11 -1
  209. data/ext/boost/config/stdlib/libcomo.hpp +1 -0
  210. data/ext/boost/config/stdlib/libstdcpp3.hpp +1 -0
  211. data/ext/boost/config/stdlib/modena.hpp +1 -0
  212. data/ext/boost/config/stdlib/msl.hpp +1 -0
  213. data/ext/boost/config/stdlib/roguewave.hpp +1 -0
  214. data/ext/boost/config/stdlib/sgi.hpp +1 -0
  215. data/ext/boost/config/stdlib/stlport.hpp +1 -0
  216. data/ext/boost/config/stdlib/vacpp.hpp +1 -0
  217. data/ext/boost/config/suffix.hpp +40 -2
  218. data/ext/boost/cstdint.hpp +36 -7
  219. data/ext/boost/date_time/gregorian/conversion.hpp +4 -2
  220. data/ext/boost/date_time/microsec_time_clock.hpp +7 -7
  221. data/ext/boost/date_time/posix_time/conversion.hpp +4 -2
  222. data/ext/boost/date_time/time_facet.hpp +43 -4
  223. data/ext/boost/detail/endian.hpp +5 -2
  224. data/ext/boost/detail/lcast_precision.hpp +2 -2
  225. data/ext/boost/detail/sp_typeinfo.hpp +1 -1
  226. data/ext/boost/detail/workaround.hpp +5 -0
  227. data/ext/boost/exception/detail/error_info_impl.hpp +3 -3
  228. data/ext/boost/exception/detail/exception_ptr.hpp +76 -135
  229. data/ext/boost/exception/detail/is_output_streamable.hpp +15 -2
  230. data/ext/boost/exception/detail/type_info.hpp +9 -5
  231. data/ext/boost/exception/diagnostic_information.hpp +5 -3
  232. data/ext/boost/exception/exception.hpp +60 -46
  233. data/ext/boost/exception/info.hpp +47 -14
  234. data/ext/boost/function/function_base.hpp +4 -4
  235. data/ext/boost/integer.hpp +4 -0
  236. data/ext/boost/integer_fwd.hpp +9 -3
  237. data/ext/boost/iterator/iterator_concepts.hpp +284 -0
  238. data/ext/boost/iterator/transform_iterator.hpp +0 -1
  239. data/ext/boost/make_shared.hpp +17 -0
  240. data/ext/boost/mpl/aux_/config/has_xxx.hpp +4 -3
  241. data/ext/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp +2 -6
  242. data/ext/boost/mpl/aux_/template_arity.hpp +4 -4
  243. data/ext/boost/mpl/eval_if.hpp +3 -3
  244. data/ext/boost/mpl/has_xxx.hpp +369 -3
  245. data/ext/boost/optional/optional.hpp +3 -1
  246. data/ext/boost/optional/optional_fwd.hpp +1 -1
  247. data/ext/boost/preprocessor/repetition/enum_trailing_params.hpp +38 -0
  248. data/ext/boost/range/algorithm/equal.hpp +188 -0
  249. data/ext/boost/range/as_literal.hpp +15 -15
  250. data/ext/boost/range/concepts.hpp +331 -0
  251. data/ext/boost/range/const_iterator.hpp +7 -4
  252. data/ext/boost/range/detail/extract_optional_type.hpp +52 -0
  253. data/ext/boost/range/detail/implementation_help.hpp +7 -7
  254. data/ext/boost/range/detail/misc_concept.hpp +33 -0
  255. data/ext/boost/range/iterator.hpp +32 -32
  256. data/ext/boost/range/iterator_range.hpp +8 -651
  257. data/ext/boost/range/iterator_range_core.hpp +542 -0
  258. data/ext/boost/range/iterator_range_io.hpp +93 -0
  259. data/ext/boost/range/mutable_iterator.hpp +7 -4
  260. data/ext/boost/range/size.hpp +1 -1
  261. data/ext/boost/range/size_type.hpp +2 -1
  262. data/ext/boost/shared_array.hpp +19 -0
  263. data/ext/boost/smart_ptr/detail/sp_convertible.hpp +2 -2
  264. data/ext/boost/smart_ptr/detail/yield_k.hpp +1 -1
  265. data/ext/boost/smart_ptr/make_shared.hpp +508 -0
  266. data/ext/boost/smart_ptr/shared_array.hpp +147 -0
  267. data/ext/boost/src/pthread/thread.cpp +16 -21
  268. data/ext/boost/src/pthread/timeconv.inl +7 -4
  269. data/ext/boost/thread/barrier.hpp +2 -1
  270. data/ext/boost/thread/detail/config.hpp +7 -1
  271. data/ext/boost/thread/detail/platform.hpp +1 -1
  272. data/ext/boost/thread/detail/thread.hpp +62 -18
  273. data/ext/boost/thread/detail/thread_group.hpp +5 -2
  274. data/ext/boost/thread/detail/tss_hooks.hpp +8 -25
  275. data/ext/boost/thread/future.hpp +45 -34
  276. data/ext/boost/thread/locks.hpp +184 -55
  277. data/ext/boost/thread/pthread/condition_variable.hpp +7 -7
  278. data/ext/boost/thread/pthread/condition_variable_fwd.hpp +4 -2
  279. data/ext/boost/thread/pthread/mutex.hpp +29 -17
  280. data/ext/boost/thread/pthread/once.hpp +5 -0
  281. data/ext/boost/thread/pthread/recursive_mutex.hpp +97 -18
  282. data/ext/boost/thread/pthread/shared_mutex.hpp +1 -1
  283. data/ext/boost/thread/pthread/thread_heap_alloc.hpp +1 -1
  284. data/ext/boost/thread/tss.hpp +2 -0
  285. data/ext/boost/throw_exception.hpp +21 -5
  286. data/ext/boost/token_functions.hpp +111 -91
  287. data/ext/boost/type_traits/add_reference.hpp +19 -1
  288. data/ext/boost/type_traits/function_traits.hpp +2 -2
  289. data/ext/boost/type_traits/is_const.hpp +24 -5
  290. data/ext/boost/type_traits/is_convertible.hpp +1 -1
  291. data/ext/boost/type_traits/is_function.hpp +3 -0
  292. data/ext/boost/type_traits/is_lvalue_reference.hpp +118 -0
  293. data/ext/boost/type_traits/is_reference.hpp +8 -81
  294. data/ext/boost/type_traits/is_rvalue_reference.hpp +29 -0
  295. data/ext/boost/type_traits/is_same.hpp +2 -2
  296. data/ext/boost/type_traits/is_volatile.hpp +26 -7
  297. data/ext/boost/type_traits/remove_const.hpp +12 -0
  298. data/ext/boost/type_traits/remove_cv.hpp +23 -1
  299. data/ext/boost/type_traits/remove_reference.hpp +21 -1
  300. data/ext/boost/type_traits/type_with_alignment.hpp +10 -10
  301. data/ext/boost/units/detail/utility.hpp +104 -0
  302. data/ext/boost/utility/compare_pointees.hpp +1 -1
  303. data/ext/common/AgentsStarter.hpp +151 -161
  304. data/ext/common/ApplicationPool/Pool.h +16 -4
  305. data/ext/common/Constants.h +1 -1
  306. data/ext/common/EventedClient.h +130 -26
  307. data/ext/common/Exceptions.h +15 -2
  308. data/ext/common/FileDescriptor.h +76 -12
  309. data/ext/common/IniFile.h +488 -0
  310. data/ext/common/LoggingAgent/LoggingServer.h +2 -2
  311. data/ext/common/LoggingAgent/RemoteSender.h +15 -6
  312. data/ext/common/MessageChannel.h +17 -101
  313. data/ext/common/PoolOptions.h +1 -0
  314. data/ext/common/ResourceLocator.h +78 -28
  315. data/ext/common/SafeLibev.h +149 -0
  316. data/ext/common/ServerInstanceDir.h +11 -7
  317. data/ext/common/Session.h +1 -1
  318. data/ext/common/SpawnManager.h +14 -14
  319. data/ext/common/StaticString.h +75 -0
  320. data/ext/common/Utils.cpp +304 -12
  321. data/ext/common/Utils.h +17 -0
  322. data/ext/common/Utils/BufferedIO.h +196 -0
  323. data/ext/common/Utils/IOUtils.cpp +159 -0
  324. data/ext/common/Utils/IOUtils.h +118 -1
  325. data/ext/common/Utils/ProcessMetricsCollector.h +184 -56
  326. data/ext/common/Utils/StrIntUtils.cpp +45 -11
  327. data/ext/common/Utils/StrIntUtils.h +8 -5
  328. data/ext/common/Utils/Timer.h +22 -0
  329. data/ext/common/Utils/utf8.h +35 -0
  330. data/ext/common/Utils/utf8/checked.h +324 -0
  331. data/ext/common/Utils/utf8/core.h +359 -0
  332. data/ext/common/Utils/utf8/unchecked.h +229 -0
  333. data/ext/common/Watchdog.cpp +52 -85
  334. data/ext/libev/config.h +122 -0
  335. data/ext/nginx/Configuration.c +7 -1
  336. data/ext/nginx/HelperAgent.cpp +16 -18
  337. data/ext/nginx/config +6 -4
  338. data/ext/oxt/system_calls.cpp +10 -0
  339. data/ext/oxt/system_calls.hpp +2 -0
  340. data/lib/phusion_passenger.rb +6 -11
  341. data/lib/phusion_passenger/dependencies.rb +2 -0
  342. data/lib/phusion_passenger/packaging.rb +5 -5
  343. data/lib/phusion_passenger/platform_info.rb +88 -0
  344. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +3 -17
  345. data/lib/phusion_passenger/platform_info/compiler.rb +14 -32
  346. data/lib/phusion_passenger/platform_info/curl.rb +6 -1
  347. data/lib/phusion_passenger/platform_info/operating_system.rb +107 -0
  348. data/lib/phusion_passenger/public_api.rb +2 -2
  349. data/lib/phusion_passenger/rails3_extensions/init.rb +5 -2
  350. data/lib/phusion_passenger/standalone/command.rb +6 -2
  351. data/lib/phusion_passenger/standalone/package_runtime_command.rb +2 -2
  352. data/lib/phusion_passenger/standalone/runtime_installer.rb +17 -5
  353. data/lib/phusion_passenger/standalone/start_command.rb +12 -12
  354. data/lib/phusion_passenger/standalone/stop_command.rb +3 -3
  355. data/lib/phusion_passenger/standalone/utils.rb +6 -2
  356. data/lib/phusion_passenger/templates/standalone/config.erb +37 -5
  357. data/lib/phusion_passenger/utils.rb +4 -7
  358. data/resources/mime.types +73 -0
  359. data/{misc → resources}/union_station_gateway.crt +0 -0
  360. data/test/cxx/BufferedIOTest.cpp +364 -0
  361. data/test/cxx/EventedClientTest.cpp +150 -13
  362. data/test/cxx/IOUtilsTest.cpp +399 -1
  363. data/test/cxx/MessageChannelTest.cpp +5 -120
  364. data/test/cxx/ProcessMetricsCollectorTest.cpp +121 -0
  365. data/test/cxx/StaticStringTest.cpp +134 -0
  366. data/test/cxx/UtilsTest.cpp +16 -46
  367. data/test/stub/rails_apps/2.3/mycook/public/dispatch.cgi +2 -2
  368. data/test/stub/rails_apps/2.3/mycook/public/dispatch.fcgi +1 -1
  369. data/test/stub/rails_apps/2.3/mycook/public/dispatch.rb +1 -1
  370. data/test/stub/rails_apps/3.0/empty/Gemfile.lock +73 -0
  371. data/test/support/allocate_memory.c +14 -0
  372. data/test/support/test_helper.rb +3 -0
  373. metadata +57 -174
  374. data/bin/passenger-stress-test +0 -345
  375. data/debian/postinst +0 -24
  376. data/doc/rdoc/classes/ConditionVariable.html +0 -215
  377. data/doc/rdoc/classes/Exception.html +0 -120
  378. data/doc/rdoc/classes/GC.html +0 -113
  379. data/doc/rdoc/classes/IO.html +0 -221
  380. data/doc/rdoc/classes/PhusionPassenger.html +0 -397
  381. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +0 -180
  382. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +0 -647
  383. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +0 -654
  384. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/InvalidPassword.html +0 -92
  385. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +0 -97
  386. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +0 -96
  387. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +0 -97
  388. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +0 -96
  389. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +0 -619
  390. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +0 -142
  391. data/doc/rdoc/classes/PhusionPassenger/AdminTools/MemoryStats.html +0 -368
  392. data/doc/rdoc/classes/PhusionPassenger/AdminTools/MemoryStats/Process.html +0 -231
  393. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance.html +0 -588
  394. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/CorruptedDirectoryError.html +0 -92
  395. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/GenerationsAbsentError.html +0 -92
  396. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Group.html +0 -147
  397. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Process.html +0 -279
  398. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/RoleDeniedError.html +0 -92
  399. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/StaleDirectoryError.html +0 -92
  400. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Stats.html +0 -123
  401. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/UnsupportedGenerationStructureVersionError.html +0 -92
  402. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger.html +0 -341
  403. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger/Log.html +0 -294
  404. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger/SharedData.html +0 -199
  405. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +0 -155
  406. data/doc/rdoc/classes/PhusionPassenger/AppProcess.html +0 -367
  407. data/doc/rdoc/classes/PhusionPassenger/ClassicRails.html +0 -95
  408. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/ApplicationSpawner.html +0 -351
  409. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/ApplicationSpawner/Error.html +0 -98
  410. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/CGIFixed.html +0 -200
  411. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/FrameworkSpawner.html +0 -410
  412. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/FrameworkSpawner/Error.html +0 -98
  413. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/RequestHandler.html +0 -156
  414. data/doc/rdoc/classes/PhusionPassenger/ClassicRailsExtensions.html +0 -115
  415. data/doc/rdoc/classes/PhusionPassenger/ClassicRailsExtensions/AnalyticsLogging.html +0 -202
  416. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +0 -172
  417. data/doc/rdoc/classes/PhusionPassenger/DebugLogging.html +0 -273
  418. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +0 -145
  419. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +0 -162
  420. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +0 -141
  421. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +0 -92
  422. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +0 -673
  423. data/doc/rdoc/classes/PhusionPassenger/MessageChannel/InvalidHashError.html +0 -92
  424. data/doc/rdoc/classes/PhusionPassenger/MessageClient.html +0 -415
  425. data/doc/rdoc/classes/PhusionPassenger/NativeSupportLoader.html +0 -134
  426. data/doc/rdoc/classes/PhusionPassenger/Packaging.html +0 -129
  427. data/doc/rdoc/classes/PhusionPassenger/PlatformInfo.html +0 -1809
  428. data/doc/rdoc/classes/PhusionPassenger/Plugin.html +0 -237
  429. data/doc/rdoc/classes/PhusionPassenger/Rack.html +0 -91
  430. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +0 -312
  431. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner/Error.html +0 -98
  432. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +0 -218
  433. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions.html +0 -114
  434. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging.html +0 -256
  435. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ACExtension.html +0 -139
  436. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ASBenchmarkableExtension.html +0 -118
  437. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ExceptionLogger.html +0 -135
  438. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +0 -378
  439. data/doc/rdoc/classes/PhusionPassenger/Standalone.html +0 -111
  440. data/doc/rdoc/classes/PhusionPassenger/Standalone/AppFinder.html +0 -252
  441. data/doc/rdoc/classes/PhusionPassenger/Standalone/Command.html +0 -161
  442. data/doc/rdoc/classes/PhusionPassenger/Standalone/ConfigFile.html +0 -368
  443. data/doc/rdoc/classes/PhusionPassenger/Standalone/ConfigFile/DisallowedContextError.html +0 -132
  444. data/doc/rdoc/classes/PhusionPassenger/Standalone/HelpCommand.html +0 -151
  445. data/doc/rdoc/classes/PhusionPassenger/Standalone/Main.html +0 -189
  446. data/doc/rdoc/classes/PhusionPassenger/Standalone/PackageRuntimeCommand.html +0 -177
  447. data/doc/rdoc/classes/PhusionPassenger/Standalone/RuntimeInstaller.html +0 -341
  448. data/doc/rdoc/classes/PhusionPassenger/Standalone/StartCommand.html +0 -203
  449. data/doc/rdoc/classes/PhusionPassenger/Standalone/StatusCommand.html +0 -156
  450. data/doc/rdoc/classes/PhusionPassenger/Standalone/StopCommand.html +0 -168
  451. data/doc/rdoc/classes/PhusionPassenger/Standalone/Utils.html +0 -86
  452. data/doc/rdoc/classes/PhusionPassenger/Standalone/VersionCommand.html +0 -135
  453. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +0 -125
  454. data/doc/rdoc/classes/PhusionPassenger/Utils.html +0 -1550
  455. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher.html +0 -204
  456. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher/DirInfo.html +0 -171
  457. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher/FileInfo.html +0 -140
  458. data/doc/rdoc/classes/PhusionPassenger/Utils/HostsFileParser.html +0 -260
  459. data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +0 -169
  460. data/doc/rdoc/classes/PhusionPassenger/Utils/RewindableInput.html +0 -265
  461. data/doc/rdoc/classes/PhusionPassenger/Utils/RewindableInput/Tempfile.html +0 -120
  462. data/doc/rdoc/classes/PhusionPassenger/Utils/UnseekableSocket.html +0 -561
  463. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +0 -140
  464. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +0 -89
  465. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +0 -182
  466. data/doc/rdoc/classes/Process.html +0 -115
  467. data/doc/rdoc/classes/Signal.html +0 -139
  468. data/doc/rdoc/created.rid +0 -1
  469. data/doc/rdoc/files/DEVELOPERS_TXT.html +0 -276
  470. data/doc/rdoc/files/README.html +0 -157
  471. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +0 -130
  472. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +0 -135
  473. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +0 -126
  474. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +0 -128
  475. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/memory_stats_rb.html +0 -126
  476. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/server_instance_rb.html +0 -132
  477. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +0 -122
  478. data/doc/rdoc/files/lib/phusion_passenger/analytics_logger_rb.html +0 -129
  479. data/doc/rdoc/files/lib/phusion_passenger/app_process_rb.html +0 -127
  480. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/application_spawner_rb.html +0 -141
  481. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/cgi_fixed_rb.html +0 -126
  482. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/framework_spawner_rb.html +0 -146
  483. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/request_handler_rb.html +0 -125
  484. data/doc/rdoc/files/lib/phusion_passenger/classic_rails_extensions/init_rb.html +0 -132
  485. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +0 -126
  486. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +0 -122
  487. data/doc/rdoc/files/lib/phusion_passenger/debug_logging_rb.html +0 -122
  488. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +0 -147
  489. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +0 -122
  490. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +0 -127
  491. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +0 -120
  492. data/doc/rdoc/files/lib/phusion_passenger/message_client_rb.html +0 -127
  493. data/doc/rdoc/files/lib/phusion_passenger/native_support_rb.html +0 -132
  494. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +0 -122
  495. data/doc/rdoc/files/lib/phusion_passenger/platform_info/apache_rb.html +0 -127
  496. data/doc/rdoc/files/lib/phusion_passenger/platform_info/binary_compatibility_rb.html +0 -129
  497. data/doc/rdoc/files/lib/phusion_passenger/platform_info/compiler_rb.html +0 -126
  498. data/doc/rdoc/files/lib/phusion_passenger/platform_info/curl_rb.html +0 -126
  499. data/doc/rdoc/files/lib/phusion_passenger/platform_info/documentation_tools_rb.html +0 -126
  500. data/doc/rdoc/files/lib/phusion_passenger/platform_info/linux_rb.html +0 -126
  501. data/doc/rdoc/files/lib/phusion_passenger/platform_info/operating_system_rb.html +0 -127
  502. data/doc/rdoc/files/lib/phusion_passenger/platform_info/ruby_rb.html +0 -128
  503. data/doc/rdoc/files/lib/phusion_passenger/platform_info/zlib_rb.html +0 -126
  504. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +0 -122
  505. data/doc/rdoc/files/lib/phusion_passenger/plugin_rb.html +0 -127
  506. data/doc/rdoc/files/lib/phusion_passenger/public_api_rb.html +0 -127
  507. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +0 -137
  508. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +0 -125
  509. data/doc/rdoc/files/lib/phusion_passenger/rails3_extensions/init_rb.html +0 -127
  510. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +0 -122
  511. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +0 -160
  512. data/doc/rdoc/files/lib/phusion_passenger/standalone/app_finder_rb.html +0 -127
  513. data/doc/rdoc/files/lib/phusion_passenger/standalone/command_rb.html +0 -135
  514. data/doc/rdoc/files/lib/phusion_passenger/standalone/config_file_rb.html +0 -126
  515. data/doc/rdoc/files/lib/phusion_passenger/standalone/help_command_rb.html +0 -126
  516. data/doc/rdoc/files/lib/phusion_passenger/standalone/main_rb.html +0 -126
  517. data/doc/rdoc/files/lib/phusion_passenger/standalone/package_runtime_command_rb.html +0 -127
  518. data/doc/rdoc/files/lib/phusion_passenger/standalone/runtime_installer_rb.html +0 -133
  519. data/doc/rdoc/files/lib/phusion_passenger/standalone/start_command_rb.html +0 -136
  520. data/doc/rdoc/files/lib/phusion_passenger/standalone/status_command_rb.html +0 -126
  521. data/doc/rdoc/files/lib/phusion_passenger/standalone/stop_command_rb.html +0 -126
  522. data/doc/rdoc/files/lib/phusion_passenger/standalone/utils_rb.html +0 -126
  523. data/doc/rdoc/files/lib/phusion_passenger/standalone/version_command_rb.html +0 -127
  524. data/doc/rdoc/files/lib/phusion_passenger/utils/file_system_watcher_rb.html +0 -126
  525. data/doc/rdoc/files/lib/phusion_passenger/utils/hosts_file_parser_rb.html +0 -120
  526. data/doc/rdoc/files/lib/phusion_passenger/utils/rewindable_input_rb.html +0 -100
  527. data/doc/rdoc/files/lib/phusion_passenger/utils/tmpdir_rb.html +0 -122
  528. data/doc/rdoc/files/lib/phusion_passenger/utils/unseekable_socket_rb.html +0 -126
  529. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +0 -179
  530. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +0 -132
  531. data/doc/rdoc/fr_class_index.html +0 -138
  532. data/doc/rdoc/fr_file_index.html +0 -108
  533. data/doc/rdoc/fr_method_index.html +0 -430
  534. data/doc/rdoc/index.html +0 -26
  535. data/doc/rdoc/rdoc-style.css +0 -187
  536. data/ext/apache2/LICENSE-CNRI.TXT +0 -79
  537. data/ext/common/Utils/BlockingScalar.h +0 -50
  538. data/ext/common/Utils/FileHandleGuard.h +0 -81
@@ -483,9 +483,16 @@ private:
483
483
  result << "<has_metrics>true</has_metrics>";
484
484
  result << "<cpu>" << (int) metrics.cpu << "</cpu>";
485
485
  result << "<rss>" << metrics.rss << "</rss>";
486
- if (metrics.realMemory != 0) {
487
- result << "<real_memory>" << metrics.realMemory << "</real_memory>";
486
+ if (metrics.pss != -1) {
487
+ result << "<pss>" << metrics.pss << "</pss>";
488
488
  }
489
+ if (metrics.privateDirty != -1) {
490
+ result << "<private_dirty>" << metrics.privateDirty << "</private_dirty>";
491
+ }
492
+ if (metrics.swap != -1) {
493
+ result << "<swap>" << metrics.swap << "</swap>";
494
+ }
495
+ result << "<real_memory>" << metrics.realMemory() << "</real_memory>";
489
496
  result << "<vmsize>" << metrics.vmsize << "</vmsize>";
490
497
  result << "<process_group_id>" << metrics.processGroupId << "</process_group_id>";
491
498
  result << "<command>" << escapeForXml(metrics.command) << "</command>";
@@ -804,7 +811,7 @@ private:
804
811
  // Now collect the process metrics and store them in the
805
812
  // data structures, and log the state into the analytics logs.
806
813
  UPDATE_TRACE_POINT();
807
- ProcessMetricsCollector::Map allMetrics =
814
+ ProcessMetricMap allMetrics =
808
815
  processMetricsCollector.collect(pids);
809
816
 
810
817
  UPDATE_TRACE_POINT();
@@ -822,13 +829,18 @@ private:
822
829
  stringstream xml;
823
830
 
824
831
  if (group->analytics && analyticsLogger != NULL) {
832
+ ssize_t shared;
825
833
  log = analyticsLogger->newTransaction(group->name,
826
834
  "processes", group->unionStationKey);
827
835
  xml << "Processes: <processes>";
836
+ xml << "<total_memory>" << allMetrics.totalMemory(shared) << "</total_memory>";
837
+ if (shared != -1) {
838
+ xml << "<total_shared_memory>" << shared << "</total_shared_memory>";
839
+ }
828
840
  }
829
841
  for (; process_info_it != process_info_it_end; process_info_it++) {
830
842
  ProcessInfoPtr &processInfo = *process_info_it;
831
- ProcessMetricsCollector::Map::const_iterator metrics_it =
843
+ ProcessMetricMap::const_iterator metrics_it =
832
844
  allMetrics.find(processInfo->process->getPid());
833
845
  if (metrics_it != allMetrics.end()) {
834
846
  processInfo->metrics = metrics_it->second;
@@ -26,7 +26,7 @@
26
26
  #define _PASSENGER_CONSTANTS_H_
27
27
 
28
28
  /* Don't forget to update lib/phusion_passenger.rb too. */
29
- #define PASSENGER_VERSION "3.0.0"
29
+ #define PASSENGER_VERSION "3.0.1"
30
30
 
31
31
  #define FEEDBACK_FD 3
32
32
 
@@ -123,7 +123,8 @@ private:
123
123
  * method fails to send all data immediately and EventedClient
124
124
  * schedules some data to be sent later, when the socket becomes
125
125
  * readable again. In here we will be watching for read
126
- * and write events.
126
+ * and write events. Once all data has been sent out the system
127
+ * will transition back to EC_CONNECTED.
127
128
  */
128
129
  EC_WRITES_PENDING,
129
130
 
@@ -140,8 +141,26 @@ private:
140
141
  EC_TOO_MANY_WRITES_PENDING,
141
142
 
142
143
  /**
143
- * This state is entered from the EC_WRITES_PENDING or the
144
- * EC_TOO_MANY_WRITES_PENDING state when disconnect() is called.
144
+ * This state is like EC_CONNECTED, but indicates that the write
145
+ * side of the connection has been closed. In this state write()
146
+ * calls won't have any effect.
147
+ */
148
+ EC_RO_CONNECTED,
149
+
150
+ /**
151
+ * This state is entered from EC_WRITES_PENDING when
152
+ * closeWrite() has been called. The system will continue
153
+ * to send out pending data but write() calls won't append more
154
+ * data to the outbox. After pending data has been sent out,
155
+ * the system will transition to EC_RO_CONNECTED.
156
+ */
157
+ EC_RO_CONNECTED_WITH_WRITES_PENDING,
158
+
159
+ /**
160
+ * This state is entered from the EC_WRITES_PENDING,
161
+ * EC_TOO_MANY_WRITES_PENDING, EC_RO_CONNECTED_WITH_WIRTES_PENDING
162
+ * or EC_RO_CONNECTED_WITH_TOO_MANY_WRITES_PENDING state when
163
+ * disconnect() is called.
145
164
  * It means that we want to close the connection as soon as all
146
165
  * pending outgoing data has been sent. As soon as that happens
147
166
  * it'll transition to EC_DISCONNECTED. In this state no further
@@ -163,14 +182,16 @@ private:
163
182
  /** Storage for data that could not be sent out immediately. */
164
183
  string outbox;
165
184
  int refcount;
166
- bool m_notifyReads;
167
185
  unsigned int outboxLimit;
186
+ bool m_notifyReads;
168
187
 
169
188
  void _onReadable(ev::io &w, int revents) {
170
189
  emitEvent(onReadable);
171
190
  }
172
191
 
173
192
  void onWritable(ev::io &w, int revents) {
193
+ assert(state != EC_CONNECTED);
194
+ assert(state != EC_RO_CONNECTED);
174
195
  assert(state != EC_DISCONNECTED);
175
196
 
176
197
  this_thread::disable_interruption di;
@@ -185,7 +206,11 @@ private:
185
206
  if (ret == -1) {
186
207
  if (errno != EAGAIN) {
187
208
  int e = errno;
188
- disconnect(true);
209
+ if (writeErrorAction == DISCONNECT_FULL) {
210
+ disconnect(true);
211
+ } else {
212
+ closeWrite();
213
+ }
189
214
  emitSystemErrorEvent("Cannot write data to client", e);
190
215
  return;
191
216
  }
@@ -213,6 +238,7 @@ private:
213
238
  if (outbox.empty()) {
214
239
  switch (state) {
215
240
  case EC_CONNECTED:
241
+ case EC_RO_CONNECTED:
216
242
  watchReadEvents(m_notifyReads);
217
243
  watchWriteEvents(false);
218
244
  break;
@@ -222,6 +248,11 @@ private:
222
248
  watchReadEvents(m_notifyReads);
223
249
  watchWriteEvents(false);
224
250
  break;
251
+ case EC_RO_CONNECTED_WITH_WRITES_PENDING:
252
+ state = EC_RO_CONNECTED;
253
+ watchReadEvents(m_notifyReads);
254
+ watchWriteEvents(false);
255
+ break;
225
256
  case EC_DISCONNECTING_WITH_WRITES_PENDING:
226
257
  state = EC_DISCONNECTED;
227
258
  watchReadEvents(false);
@@ -252,7 +283,12 @@ private:
252
283
  watchWriteEvents(true);
253
284
  }
254
285
  break;
286
+ case EC_RO_CONNECTED:
287
+ fprintf(stderr, "BUG: when outbox is non-empty the state should never be EC_RO_CONNECTED!\n");
288
+ abort();
289
+ break;
255
290
  case EC_WRITES_PENDING:
291
+ case EC_RO_CONNECTED_WITH_WRITES_PENDING:
256
292
  watchReadEvents(m_notifyReads);
257
293
  watchWriteEvents(true);
258
294
  break;
@@ -300,6 +336,14 @@ public:
300
336
  /** The client's file descriptor. Could be -1: see <tt>ioAllowed()</tt>. */
301
337
  FileDescriptor fd;
302
338
 
339
+ /** Controls what to do when a write error is encountered. */
340
+ enum {
341
+ /** Forcefully disconnect the client. */
342
+ DISCONNECT_FULL,
343
+ /** Close the writer side of the connection, but continue allowing reading. */
344
+ DISCONNECT_WRITE
345
+ } writeErrorAction;
346
+
303
347
  /**
304
348
  * Called when the file descriptor becomes readable and read notifications
305
349
  * are enabled (see <tt>notifyRead()</tt>). When there's too much pending
@@ -350,16 +394,17 @@ public:
350
394
  writeWatcher(loop),
351
395
  fd(_fd)
352
396
  {
353
- state = EC_CONNECTED;
354
- refcount = 1;
355
- m_notifyReads = false;
356
- outboxLimit = 1024 * 32;
357
- onReadable = NULL;
358
- onDisconnect = NULL;
359
- onDetach = NULL;
397
+ state = EC_CONNECTED;
398
+ refcount = 1;
399
+ m_notifyReads = false;
400
+ outboxLimit = 1024 * 32;
401
+ writeErrorAction = DISCONNECT_FULL;
402
+ onReadable = NULL;
403
+ onDisconnect = NULL;
404
+ onDetach = NULL;
360
405
  onPendingDataFlushed = NULL;
361
- onSystemError = NULL;
362
- userData = NULL;
406
+ onSystemError = NULL;
407
+ userData = NULL;
363
408
  readWatcher.set(fd, ev::READ);
364
409
  readWatcher.set<EventedClient, &EventedClient::_onReadable>(this);
365
410
  writeWatcher.set<EventedClient, &EventedClient::onWritable>(this);
@@ -393,17 +438,35 @@ public:
393
438
  }
394
439
 
395
440
  /**
396
- * Returns whether it is allowed to perform any I/O with this client.
441
+ * Returns whether it is allowed to perform some kind of I/O with
442
+ * this client, either reading or writing.
397
443
  * Usually true, and false when the client is either being disconnected
398
444
  * or has been disconnected. A return value of false indicates that
399
445
  * <tt>fd</tt> might be -1, but even when it isn't -1 you shouldn't
400
446
  * access <tt>fd</tt> anymore.
447
+ * When the connection is half-closed (e.g. after closeWrite() has
448
+ * been called) the return value is still be true. Only when I/O of any
449
+ * kind is disallowed will this function return false.
401
450
  */
402
451
  bool ioAllowed() const {
403
452
  return state != EC_DISCONNECTING_WITH_WRITES_PENDING
404
453
  && state != EC_DISCONNECTED;
405
454
  }
406
455
 
456
+ /**
457
+ * Returns whether it is allowed to write data to the client.
458
+ * Usually true, and false when the client is either being disconnected
459
+ * or has been disconnected or when the writer side of the client
460
+ * connection has been closed. write() will do nothing if this function
461
+ * returns false.
462
+ */
463
+ bool writeAllowed() const {
464
+ return state == EC_CONNECTED
465
+ || state == EC_WRITES_PENDING
466
+ || state == EC_TOO_MANY_WRITES_PENDING
467
+ || state == EC_RO_CONNECTED_WITH_WRITES_PENDING;
468
+ }
469
+
407
470
  /** Used by unit tests. */
408
471
  bool readWatcherActive() const {
409
472
  return readWatcher.is_active();
@@ -476,12 +539,15 @@ public:
476
539
  * network congestion) then the data will be buffered and scheduled for
477
540
  * sending later.
478
541
  *
479
- * If an I/O error was encountered then the client connection will be
480
- * closed by calling <tt>disconnect(true)</tt>. This means this method
481
- * could potentially call the <tt>onDisconnect</tt> callback.
542
+ * If an I/O error was encountered then the action taken depends on the
543
+ * value of <em>writeActionError</em>. By default it is DISCONNECT_FULL,
544
+ * meaning the client connection will be closed by calling
545
+ * <tt>disconnect(true)</tt>. This means this method could potentially
546
+ * call the <tt>onDisconnect</tt> callback.
482
547
  *
483
- * If the client connection is already being closed or has already
484
- * been closed then this method does nothing.
548
+ * If the client connection is already being closed, has already
549
+ * been closed or if the writer side is closed, then this method does
550
+ * nothing.
485
551
  *
486
552
  * The <tt>onPendingDataFlushed</tt> callback will be called after
487
553
  * this data and whatever existing pending data have been written
@@ -489,7 +555,7 @@ public:
489
555
  * of time.
490
556
  */
491
557
  void write(const StaticString data[], unsigned int count) {
492
- if (!ioAllowed()) {
558
+ if (!writeAllowed()) {
493
559
  return;
494
560
  }
495
561
 
@@ -500,7 +566,11 @@ public:
500
566
  ret = gatheredWrite(fd, data, count, outbox);
501
567
  if (ret == -1) {
502
568
  int e = errno;
503
- disconnect(true);
569
+ if (writeErrorAction == DISCONNECT_FULL) {
570
+ disconnect(true);
571
+ } else {
572
+ closeWrite();
573
+ }
504
574
  emitSystemErrorEvent("Cannot write data to client", e);
505
575
  } else {
506
576
  updateWatcherStates();
@@ -510,6 +580,39 @@ public:
510
580
  }
511
581
  }
512
582
 
583
+ /**
584
+ * Close only the writer side of the client connection.
585
+ * After calling this method, subsequent write() calls won't do anything
586
+ * anymore. Any pending outgoing data will be sent out whenever the
587
+ * opportunity arises.
588
+ *
589
+ * This function does nothing if the client is being disconnected,
590
+ * already disconnected or if only the writer side is closed.
591
+ */
592
+ void closeWrite() {
593
+ this_thread::disable_syscall_interruption dsi;
594
+
595
+ switch (state) {
596
+ case EC_CONNECTED:
597
+ assert(outbox.empty());
598
+ state = EC_RO_CONNECTED;
599
+ if (syscalls::shutdown(fd, SHUT_WR) == -1) {
600
+ int e = errno;
601
+ emitSystemErrorEvent(
602
+ "Cannot shutdown writer half of the client socket",
603
+ e);
604
+ }
605
+ break;
606
+ case EC_WRITES_PENDING:
607
+ case EC_TOO_MANY_WRITES_PENDING:
608
+ state = EC_RO_CONNECTED_WITH_WRITES_PENDING;
609
+ break;
610
+ default:
611
+ break;
612
+ }
613
+ updateWatcherStates();
614
+ }
615
+
513
616
  /**
514
617
  * Disconnects the client. This actually closes the underlying file
515
618
  * descriptor, even if the FileDescriptor object still has references.
@@ -543,7 +646,7 @@ public:
543
646
  this_thread::disable_interruption di;
544
647
  this_thread::disable_syscall_interruption dsi;
545
648
 
546
- if (state == EC_CONNECTED || force) {
649
+ if (state == EC_CONNECTED || state == EC_RO_CONNECTED || force) {
547
650
  state = EC_DISCONNECTED;
548
651
  watchReadEvents(false);
549
652
  watchWriteEvents(false);
@@ -570,9 +673,10 @@ public:
570
673
  * Detaches the client file descriptor so that this EventedClient no longer
571
674
  * has any control over it. Any EventedClient I/O watchers on the client file
572
675
  * descriptor will be stopped and further I/O on the file descriptor via
573
- * EventedClient will become impossible. The original client file descriptor
574
- * is returned and <tt>onDetach</tt> is called. Subsequent calls to this
575
- * function will return -1 and will no longer call <tt>onDetach</tt>.
676
+ * EventedClient will become impossible. Any pending outgoing data will be
677
+ * discarded. The original client file descriptor is returned and
678
+ * <tt>onDetach</tt> is called. Subsequent calls to this function will
679
+ * return -1 and will no longer call <tt>onDetach</tt>.
576
680
  *
577
681
  * @post !ioAllowed()
578
682
  * @post fd == -1
@@ -204,16 +204,20 @@ class SpawnException: public oxt::tracable_exception {
204
204
  private:
205
205
  string msg;
206
206
  bool m_hasErrorPage;
207
+ bool m_isHTML;
207
208
  string m_errorPage;
208
209
  public:
209
210
  SpawnException(const string &message)
210
211
  : msg(message) {
211
212
  m_hasErrorPage = false;
213
+ m_isHTML = false;
212
214
  }
213
215
 
214
- SpawnException(const string &message, const string &errorPage)
215
- : msg(message), m_errorPage(errorPage) {
216
+ SpawnException(const string &message, const string &errorPage, bool isHTML = true)
217
+ : msg(message), m_errorPage(errorPage)
218
+ {
216
219
  m_hasErrorPage = true;
220
+ m_isHTML = isHTML;
217
221
  }
218
222
 
219
223
  virtual ~SpawnException() throw() {}
@@ -234,6 +238,15 @@ public:
234
238
  const string getErrorPage() const {
235
239
  return m_errorPage;
236
240
  }
241
+
242
+ /**
243
+ * Whether the error page content is HTML.
244
+ *
245
+ * @pre hasErrorPage()
246
+ */
247
+ bool isHTML() const {
248
+ return m_isHTML;
249
+ }
237
250
  };
238
251
 
239
252
  /**
@@ -26,20 +26,25 @@
26
26
  #define _PASSENGER_FILE_DESCRIPTOR_H_
27
27
 
28
28
  #include <boost/shared_ptr.hpp>
29
+ #include <boost/make_shared.hpp>
29
30
  #include <oxt/system_calls.hpp>
30
31
 
32
+ #include <utility>
31
33
  #include <unistd.h>
32
34
  #include <cerrno>
33
35
 
34
- #include "MessageChannel.h"
35
- #include "Exceptions.h"
36
+ #include <Exceptions.h>
36
37
 
37
38
  namespace Passenger {
38
39
 
40
+ using namespace std;
39
41
  using namespace boost;
40
42
  using namespace oxt;
41
43
 
42
44
 
45
+ void safelyClose(int fd);
46
+
47
+
43
48
  /**
44
49
  * Wrapper class around a file descriptor integer, for RAII behavior.
45
50
  *
@@ -71,17 +76,22 @@ private:
71
76
  }
72
77
  }
73
78
 
74
- void close() {
79
+ void close(bool checkErrors = true) {
75
80
  if (fd >= 0) {
76
81
  this_thread::disable_syscall_interruption dsi;
77
82
  int theFd = fd;
78
83
  fd = -1;
79
- if (syscalls::close(theFd) == -1 && errno != ENOTCONN) {
80
- int e = errno;
81
- throw SystemException("Cannot close file descriptor", e);
84
+ if (checkErrors) {
85
+ safelyClose(theFd);
86
+ } else {
87
+ syscalls::close(fd);
82
88
  }
83
89
  }
84
90
  }
91
+
92
+ void detach() {
93
+ fd = -1;
94
+ }
85
95
  };
86
96
 
87
97
  /** Shared pointer for reference counting on this file descriptor */
@@ -112,7 +122,7 @@ public:
112
122
  * }
113
123
  */
114
124
  int e = errno;
115
- data.reset(new SharedData(fd));
125
+ data = make_shared<SharedData>(fd);
116
126
  errno = e;
117
127
  }
118
128
  }
@@ -122,14 +132,37 @@ public:
122
132
  * nothing will happen. If there are multiple copies of this FileDescriptor
123
133
  * then the underlying file descriptor will be closed for every one of them.
124
134
  *
135
+ * @params checkErrors Whether a SystemException should be thrown in case
136
+ * closing the file descriptor fails. If false, errors
137
+ * are silently ignored.
125
138
  * @throws SystemException Something went wrong while closing
126
- * the file descriptor.
139
+ * the file descriptor. Only thrown if
140
+ * checkErrors is true.
141
+ * @post *this == -1
142
+ */
143
+ void close(bool checkErrors = true) {
144
+ if (data != NULL) {
145
+ data->close(checkErrors);
146
+ data.reset();
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Detach from the underlying file descriptor without closing it.
152
+ * This FileDescriptor and all copies will no longer affect the
153
+ * underlying file descriptors.
154
+ *
155
+ * @return The underlying file descriptor, or -1 if already closed.
127
156
  * @post *this == -1
128
157
  */
129
- void close() {
158
+ int detach() {
130
159
  if (data != NULL) {
131
- data->close();
160
+ int fd = data->fd;
161
+ data->detach();
132
162
  data.reset();
163
+ return fd;
164
+ } else {
165
+ return -1;
133
166
  }
134
167
  }
135
168
 
@@ -159,7 +192,7 @@ public:
159
192
  */
160
193
  int e = errno;
161
194
  if (fd >= 0) {
162
- data.reset(new SharedData(fd));
195
+ data = make_shared<SharedData>(fd);
163
196
  } else {
164
197
  data.reset();
165
198
  }
@@ -185,6 +218,33 @@ public:
185
218
  }
186
219
  };
187
220
 
221
+ /**
222
+ * A structure containing two FileDescriptor objects. Behaves like a pair
223
+ * and like a two-element array.
224
+ */
225
+ class FileDescriptorPair: public pair<FileDescriptor, FileDescriptor> {
226
+ public:
227
+ FileDescriptorPair() { }
228
+
229
+ FileDescriptorPair(const FileDescriptor &a, const FileDescriptor &b)
230
+ : pair<FileDescriptor, FileDescriptor>(a, b)
231
+ { }
232
+
233
+ FileDescriptor &operator[](int index) {
234
+ if (index == 0) {
235
+ return first;
236
+ } else if (index == 1) {
237
+ return second;
238
+ } else {
239
+ throw ArgumentException("Index must be either 0 of 1");
240
+ }
241
+ }
242
+ };
243
+
244
+ // Convenience aliases.
245
+ typedef FileDescriptorPair Pipe;
246
+ typedef FileDescriptorPair SocketPair;
247
+
188
248
  /**
189
249
  * A synchronization mechanism that's implemented with file descriptors,
190
250
  * and as such can be used in combination with select() and friends.
@@ -216,7 +276,11 @@ public:
216
276
  }
217
277
 
218
278
  void notify() {
219
- MessageChannel(writer).writeRaw("x", 1);
279
+ ssize_t ret = syscalls::write(writer, "x", 1);
280
+ if (ret == -1 && errno != EAGAIN) {
281
+ int e = errno;
282
+ throw SystemException("Cannot write notification data", e);
283
+ }
220
284
  }
221
285
 
222
286
  int fd() const {