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
@@ -356,6 +356,23 @@ string getHostName();
356
356
  */
357
357
  string getSignalName(int sig);
358
358
 
359
+ /**
360
+ * Resets the current process's signal handler disposition and signal mask
361
+ * to default values. One should call this every time one forks a child process;
362
+ * non-default signal masks/handler dispositions can cause all kinds of weird quirks,
363
+ * like waitpid() malfunctioning on OS X.
364
+ *
365
+ * This function is async-signal safe.
366
+ */
367
+ void resetSignalHandlersAndMask();
368
+
369
+ /**
370
+ * Close all file descriptors that are higher than <em>lastToKeepOpen</em>.
371
+ * This function is async-signal safe. But make sure there are no other
372
+ * threads running that might open file descriptors!
373
+ */
374
+ void closeAllFileDescriptors(int lastToKeepOpen);
375
+
359
376
 
360
377
  /**
361
378
  * Represents a buffered upload file.
@@ -0,0 +1,196 @@
1
+ #ifndef _PASSENGER_BUFFERED_IO_H_
2
+ #define _PASSENGER_BUFFERED_IO_H_
3
+
4
+ #include <string>
5
+ #include <utility>
6
+ #include <algorithm>
7
+ #include <boost/function.hpp>
8
+ #include <oxt/system_calls.hpp>
9
+ #include <oxt/macros.hpp>
10
+ #include <cstring>
11
+ #include <FileDescriptor.h>
12
+ #include <Exceptions.h>
13
+ #include <StaticString.h>
14
+ #include <Utils/IOUtils.h>
15
+
16
+ namespace Passenger {
17
+
18
+ using namespace std;
19
+ using namespace oxt;
20
+
21
+
22
+ /**
23
+ * Provides buffered I/O for arbitrary file descriptors. Supports features not
24
+ * found in C++'s iostream or libc's stdio:
25
+ * - All functions have timeout support.
26
+ * - The readLine() method returns a C++ string, so no need to worry about
27
+ * buffer management. A size limit can be imposed.
28
+ * - Read buffer is infinite in size.
29
+ * - Unreading (pushing back) arbitrary amount of data.
30
+ */
31
+ class BufferedIO {
32
+ private:
33
+ FileDescriptor fd;
34
+ string buffer;
35
+
36
+ static pair<unsigned int, bool> nReadOrEofReached(const char *data,
37
+ unsigned int size, void *output, unsigned int goalSize, unsigned int *alreadyRead)
38
+ {
39
+ char *current = (char *) output + *alreadyRead;
40
+ unsigned int remaining = goalSize - *alreadyRead;
41
+ unsigned int consumed = min(remaining, size);
42
+ memcpy(current, data, consumed);
43
+ *alreadyRead += consumed;
44
+ return make_pair(consumed, *alreadyRead == goalSize);
45
+ }
46
+
47
+ static pair<unsigned int, bool> eofReached(const char *data,
48
+ unsigned int size, string *output)
49
+ {
50
+ output->append(data, size);
51
+ return make_pair(size, false);
52
+ }
53
+
54
+ static pair<unsigned int, bool> newlineFound(const char *data,
55
+ unsigned int size, string *output, unsigned int max)
56
+ {
57
+ const char *newline = (const char *) memchr(data, '\n', size);
58
+ if (newline != NULL) {
59
+ unsigned int accepted = newline - data + 1;
60
+ if (output->size() + accepted > max) {
61
+ throw SecurityException("Line too long");
62
+ }
63
+ output->append(data, accepted);
64
+ return make_pair(accepted, true);
65
+ } else {
66
+ if (output->size() + size > max) {
67
+ throw SecurityException("Line too long");
68
+ }
69
+ output->append(data, size);
70
+ return make_pair(size, false);
71
+ }
72
+ }
73
+
74
+ public:
75
+ typedef function< pair<unsigned int, bool>(const char *data, unsigned int size) > AcceptFunction;
76
+
77
+ BufferedIO() { }
78
+
79
+ BufferedIO(const FileDescriptor &_fd)
80
+ : fd(_fd)
81
+ { }
82
+
83
+ FileDescriptor getFd() const {
84
+ return fd;
85
+ }
86
+
87
+ const string &getBuffer() const {
88
+ return buffer;
89
+ }
90
+
91
+ /**
92
+ * This method keeps reading data in a loop, feeding each chunk to the given
93
+ * acceptor function, until the function says that it has consumed all data
94
+ * that it needs. Leftover data that has been read from the file descriptor
95
+ * but not consumed by the acceptor function will be put in the buffer, making
96
+ * it available for future read operations.
97
+ *
98
+ * The acceptor function accepts (data, size) as arguments and returns a
99
+ * (consumed, done) pair, where 'consumed' indicates the number of bytes
100
+ * from 'data' that it has consumed. 'done' indicates whether the acceptor
101
+ * function is done consuming (true), or whether it expects more data (false).
102
+ *
103
+ * readUntil() can be used for e.g. reading data until a newline is encountered.
104
+ *
105
+ * If the acceptor function throws an exception then the BufferedIO instance
106
+ * will be left in an undefined state, making it unusable.
107
+ *
108
+ * @throws RuntimeException The acceptor function returned an invalid result.
109
+ * @throws SystemException
110
+ * @throws TimeoutException
111
+ * @throws boost::thread_interrupted
112
+ */
113
+ unsigned int readUntil(const AcceptFunction &acceptor, unsigned long long *timeout = NULL) {
114
+ pair<unsigned int, bool> acceptResult;
115
+ unsigned int totalRead = 0;
116
+
117
+ if (!buffer.empty()) {
118
+ acceptResult = acceptor(buffer.c_str(), buffer.size());
119
+ if (OXT_UNLIKELY(!acceptResult.second && acceptResult.first < buffer.size())) {
120
+ throw RuntimeException("Acceptor function cannot return (x,false) where x is smaller than the input size");
121
+ } else if (OXT_UNLIKELY(acceptResult.first > buffer.size())) {
122
+ throw RuntimeException("Acceptor function cannot return a larger accept count than the input size");
123
+ }
124
+ buffer.erase(0, acceptResult.first);
125
+ totalRead = acceptResult.first;
126
+ if (acceptResult.second) {
127
+ return totalRead;
128
+ }
129
+ }
130
+
131
+ while (true) {
132
+ if (OXT_UNLIKELY(timeout != NULL && !waitUntilReadable(fd, timeout))) {
133
+ throw TimeoutException("Read timeout");
134
+ }
135
+
136
+ char tmp[1024 * 8];
137
+ ssize_t ret = syscalls::read(fd, tmp, sizeof(tmp));
138
+ if (ret == 0) {
139
+ return totalRead;
140
+ } else if (OXT_UNLIKELY(ret == -1)) {
141
+ if (errno != EAGAIN) {
142
+ int e = errno;
143
+ throw SystemException("read() failed", e);
144
+ }
145
+ } else {
146
+ acceptResult = acceptor(tmp, ret);
147
+ totalRead += acceptResult.first;
148
+ if (OXT_UNLIKELY(!acceptResult.second && acceptResult.first < (unsigned int) ret)) {
149
+ throw RuntimeException("Acceptor function cannot return (x,false) where x is smaller than the input size");
150
+ } else if (OXT_UNLIKELY(acceptResult.first > (unsigned int) ret)) {
151
+ throw RuntimeException("Acceptor function cannot return a larger accept count than the input size");
152
+ }
153
+ if (acceptResult.second) {
154
+ buffer.assign(tmp + acceptResult.first, ret - acceptResult.first);
155
+ return totalRead;
156
+ }
157
+ }
158
+ }
159
+ }
160
+
161
+ unsigned int read(void *buf, unsigned int size, unsigned long long *timeout = NULL) {
162
+ unsigned int counter = 0;
163
+ return readUntil(
164
+ boost::bind(nReadOrEofReached, _1, _2, buf, size, &counter),
165
+ timeout);
166
+ }
167
+
168
+ string readAll(unsigned long long *timeout = NULL) {
169
+ string output;
170
+ readUntil(boost::bind(eofReached, _1, _2, &output), timeout);
171
+ return output;
172
+ }
173
+
174
+ string readLine(unsigned int max = 1024, unsigned long long *timeout = NULL) {
175
+ string output;
176
+ readUntil(boost::bind(newlineFound, _1, _2, &output, max), timeout);
177
+ return output;
178
+ }
179
+
180
+ void unread(const void *buf, unsigned int size) {
181
+ string newBuffer;
182
+ newBuffer.reserve(size + buffer.size());
183
+ newBuffer.append((const char *) buf, (string::size_type) size);
184
+ newBuffer.append(buffer);
185
+ buffer = newBuffer;
186
+ }
187
+
188
+ void unread(const StaticString &str) {
189
+ unread(str.c_str(), str.size());
190
+ }
191
+ };
192
+
193
+
194
+ } // namespace Passenger
195
+
196
+ #endif /* _PASSENGER_BUFFERED_IO_H_ */
@@ -49,6 +49,11 @@
49
49
  #include <cerrno>
50
50
  #include <cmath>
51
51
 
52
+ #ifdef __linux__
53
+ #include <sys/syscall.h>
54
+ #endif
55
+
56
+ #include "Timer.h"
52
57
  #include "IOUtils.h"
53
58
  #include "StrIntUtils.h"
54
59
  #include "../Exceptions.h"
@@ -149,6 +154,33 @@ setNonBlocking(int fd) {
149
154
  }
150
155
  }
151
156
 
157
+ int
158
+ tryAccept4(int sock, struct sockaddr *addr, socklen_t *addr_len, int options) {
159
+ #if defined(__linux__) && defined(__x86_64__)
160
+ int ret;
161
+ do {
162
+ ret = syscall(288, sock, addr, addr_len, options);
163
+ } while (ret == -1 && errno == EINTR);
164
+ return ret;
165
+ #elif defined(__linux__) && defined(__i386__)
166
+ int ret;
167
+ do {
168
+ ret = syscall(__NR_socketcall, 18,
169
+ sock, addr, addr_len, options);
170
+ } while (ret == -1 && errno == EINTR);
171
+ return ret;
172
+ #elif defined(SYS_ACCEPT4)
173
+ int ret;
174
+ do {
175
+ ret = ::accept4(sock, addr, addr_len, options);
176
+ } while (ret == -1 && errno == EINTR);
177
+ return ret;
178
+ #else
179
+ errno = ENOSYS;
180
+ return -1;
181
+ #endif
182
+ }
183
+
152
184
  vector<string>
153
185
  resolveHostname(const string &hostname, unsigned int port, bool shuffle) {
154
186
  string portString = toString(port);
@@ -504,6 +536,116 @@ connectToTcpServer(const StaticString &hostname, unsigned int port) {
504
536
  return fd;
505
537
  }
506
538
 
539
+ SocketPair
540
+ createUnixSocketPair() {
541
+ int fds[2];
542
+ FileDescriptor sockets[2];
543
+
544
+ if (syscalls::socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) {
545
+ int e = errno;
546
+ throw SystemException("Cannot create a Unix socket pair", e);
547
+ } else {
548
+ sockets[0] = fds[0];
549
+ sockets[1] = fds[1];
550
+ return SocketPair(sockets[0], sockets[1]);
551
+ }
552
+ }
553
+
554
+ Pipe
555
+ createPipe() {
556
+ int fds[2];
557
+ FileDescriptor p[2];
558
+
559
+ if (syscalls::pipe(fds) == -1) {
560
+ int e = errno;
561
+ throw SystemException("Cannot create a pipe", e);
562
+ } else {
563
+ p[0] = fds[0];
564
+ p[1] = fds[1];
565
+ return Pipe(p[0], p[1]);
566
+ }
567
+ }
568
+
569
+ static bool
570
+ waitUntilIOEvent(int fd, short event, unsigned long long *timeout) {
571
+ struct pollfd pfd;
572
+ int ret;
573
+
574
+ pfd.fd = fd;
575
+ pfd.events = event;
576
+ pfd.revents = 0;
577
+
578
+ Timer timer;
579
+ ret = syscalls::poll(&pfd, 1, *timeout / 1000);
580
+ if (ret == -1) {
581
+ int e = errno;
582
+ throw SystemException("poll() failed", e);
583
+ } else {
584
+ unsigned long long elapsed = timer.usecElapsed();
585
+ if (elapsed > *timeout) {
586
+ *timeout = 0;
587
+ } else {
588
+ *timeout -= elapsed;
589
+ }
590
+ return ret != 0;
591
+ }
592
+ }
593
+
594
+ bool
595
+ waitUntilReadable(int fd, unsigned long long *timeout) {
596
+ return waitUntilIOEvent(fd, POLLIN, timeout);
597
+ }
598
+
599
+ bool
600
+ waitUntilWritable(int fd, unsigned long long *timeout) {
601
+ return waitUntilIOEvent(fd, POLLOUT | POLLHUP, timeout);
602
+ }
603
+
604
+ unsigned int
605
+ readExact(int fd, void *buf, unsigned int size, unsigned long long *timeout) {
606
+ ssize_t ret;
607
+ unsigned int alreadyRead = 0;
608
+
609
+ while (alreadyRead < size) {
610
+ if (timeout != NULL && !waitUntilReadable(fd, timeout)) {
611
+ throw TimeoutException("Cannot read enough data within the specified timeout");
612
+ }
613
+ ret = syscalls::read(fd, (char *) buf + alreadyRead, size - alreadyRead);
614
+ if (ret == -1) {
615
+ int e = errno;
616
+ throw SystemException("read() failed", e);
617
+ } else if (ret == 0) {
618
+ return alreadyRead;
619
+ } else {
620
+ alreadyRead += ret;
621
+ }
622
+ }
623
+ return alreadyRead;
624
+ }
625
+
626
+ void
627
+ writeExact(int fd, const void *data, unsigned int size, unsigned long long *timeout) {
628
+ ssize_t ret;
629
+ unsigned int written = 0;
630
+ while (written < size) {
631
+ if (timeout != NULL && !waitUntilWritable(fd, timeout)) {
632
+ throw TimeoutException("Cannot write enough data within the specified timeout");
633
+ }
634
+ ret = syscalls::write(fd, (const char *) data + written, size - written);
635
+ if (ret == -1) {
636
+ int e = errno;
637
+ throw SystemException("write() failed", e);
638
+ } else {
639
+ written += ret;
640
+ }
641
+ }
642
+ }
643
+
644
+ void
645
+ writeExact(int fd, const StaticString &data, unsigned long long *timeout) {
646
+ writeExact(fd, data.c_str(), data.size(), timeout);
647
+ }
648
+
507
649
  /**
508
650
  * Converts an array of StaticStrings to a corresponding array of iovec structures,
509
651
  * returning the size sum in bytes of all StaticStrings.
@@ -750,5 +892,22 @@ setWritevFunction(WritevFunction func) {
750
892
  }
751
893
  }
752
894
 
895
+ void
896
+ safelyClose(int fd) {
897
+ if (syscalls::close(fd) == -1) {
898
+ /* FreeBSD has a kernel bug which can cause close() to return ENOTCONN.
899
+ * This is harmless, ignore it. We check for this problem on all
900
+ * platforms because some OSes might borrow Unix domain socket
901
+ * code from FreeBSD.
902
+ * http://www.freebsd.org/cgi/query-pr.cgi?pr=79138
903
+ * http://www.freebsd.org/cgi/query-pr.cgi?pr=144061
904
+ */
905
+ if (errno != ENOTCONN) {
906
+ int e = errno;
907
+ throw SystemException("Cannot close file descriptor", e);
908
+ }
909
+ }
910
+ }
911
+
753
912
 
754
913
  } // namespace Passenger
@@ -30,7 +30,8 @@
30
30
  #include <unistd.h>
31
31
  #include <string>
32
32
  #include <vector>
33
- #include "../StaticString.h"
33
+ #include <StaticString.h>
34
+ #include <FileDescriptor.h>
34
35
 
35
36
  namespace Passenger {
36
37
 
@@ -92,6 +93,12 @@ bool isLocalSocketAddress(const StaticString &address);
92
93
  */
93
94
  void setNonBlocking(int fd);
94
95
 
96
+ /**
97
+ * Try to call the Linux accept4() system call. If the system call is
98
+ * not available, then -1 is returned and errno is set to ENOSYS.
99
+ */
100
+ int callAccept4(int sock, struct sockaddr *addr, socklen_t *addr_len, int options);
101
+
95
102
  /**
96
103
  * Resolves the given host name and returns a list of IP addresses.
97
104
  * <em>hostname</em> may also be an IP address, in which case it is
@@ -193,6 +200,107 @@ int connectToUnixServer(const StaticString &filename);
193
200
  */
194
201
  int connectToTcpServer(const StaticString &hostname, unsigned int port);
195
202
 
203
+ /**
204
+ * Creates a Unix domain socket pair.
205
+ *
206
+ * @throws SystemException
207
+ * @throws boost::thread_interrupted
208
+ */
209
+ SocketPair createUnixSocketPair();
210
+
211
+ /**
212
+ * Creates a pipe.
213
+ *
214
+ * @throws SystemException
215
+ * @throws boost::thread_interrupted
216
+ */
217
+ Pipe createPipe();
218
+
219
+ /**
220
+ * Waits at most <tt>*timeout</tt> microseconds for the file descriptor to become readable.
221
+ * Returns true if it become readable within the timeout, false if the timeout expired.
222
+ *
223
+ * <tt>*timeout</tt> may be 0, in which case this method will check whether the file
224
+ * descriptor is readable, and immediately returns without waiting.
225
+ *
226
+ * If no exception is thrown, this method deducts the number of microseconds that has
227
+ * passed from <tt>*timeout</tt>.
228
+ *
229
+ * @throws SystemException
230
+ * @throws boost::thread_interrupted
231
+ */
232
+ bool waitUntilReadable(int fd, unsigned long long *timeout);
233
+
234
+ /**
235
+ * Waits at most <tt>*timeout</tt> microseconds for the file descriptor to become writable.
236
+ * Returns true if it become writable within the timeout, false if the timeout expired.
237
+ *
238
+ * <tt>*timeout</tt> may be 0, in which case this method will check whether the file
239
+ * descriptor is writable, and immediately returns without waiting.
240
+ *
241
+ * If no exception is thrown, this method deducts the number of microseconds that has
242
+ * passed from <tt>*timeout</tt>.
243
+ *
244
+ * @throws SystemException
245
+ * @throws boost::thread_interrupted
246
+ */
247
+ bool waitUntilWritable(int fd, unsigned long long *timeout);
248
+
249
+ /**
250
+ * Attempts to read exactly <tt>size</tt> bytes of data from the given file
251
+ * descriptor, and put the result in <tt>buf</tt>. On non-blocking sockets
252
+ * this function will block by poll()ing the socket.
253
+ *
254
+ * @param buf The buffer to place the read data in. This buffer must be at least
255
+ * <tt>size</tt> bytes long.
256
+ * @param size The number of bytes to read.
257
+ * @param timeout A pointer to an integer, which specifies the maximum number of
258
+ * microseconds that may be spent on reading the <tt>size</tt> bytes
259
+ * of data. If the timeout expired then TimeoutException will be
260
+ * thrown.
261
+ * If this function returns without throwing an exception, then the
262
+ * total number of microseconds spent on reading will be deducted
263
+ * from <tt>timeout</tt>.
264
+ * Pass NULL if you do not want to enforce a timeout.
265
+ * @return The number of bytes read. This is exactly equal to <em>size</em>,
266
+ * except when EOF is encountered prematurely.
267
+ * @pre buf != NULL
268
+ * @throws SystemException
269
+ * @throws TimeoutException Unable to read <tt>size</tt> bytes of data within
270
+ * <tt>timeout</tt> microseconds.
271
+ * @throws boost::thread_interrupted
272
+ */
273
+ unsigned int readExact(int fd, void *buf, unsigned int size, unsigned long long *timeout = NULL);
274
+
275
+ /**
276
+ * Writes a block of data to the given file descriptor and blocks until everything
277
+ * is written, even for non-blocking sockets. If not everything can be written (e.g.
278
+ * because the peer closed the connection before accepting everything) then an
279
+ * exception will be thrown.
280
+ *
281
+ * @note Security guarantee: this method will not copy the data in memory,
282
+ * so it's safe to use this method to write passwords to the underlying
283
+ * file descriptor.
284
+ *
285
+ * @param data The data to send.
286
+ * @param size The number of bytes in <tt>data</tt>.
287
+ * @param timeout A pointer to an integer, which specifies the maximum number of
288
+ * microseconds that may be spent on writing the <tt>size</tt> bytes
289
+ * of data. If the timeout expired then TimeoutException will be
290
+ * thrown.
291
+ * If this function returns without throwing an exception, then the
292
+ * total number of microseconds spent on writing will be deducted
293
+ * from <tt>timeout</tt>.
294
+ * Pass NULL if you do not want to enforce a timeout.
295
+ * @pre data != NULL
296
+ * @throws SystemException
297
+ * @throws TimeoutException Unable to write <tt>size</tt> bytes of data within
298
+ * <tt>timeout</tt> microseconds.
299
+ * @throws boost::thread_interrupted
300
+ */
301
+ void writeExact(int fd, const void *data, unsigned int size, unsigned long long *timeout = NULL);
302
+ void writeExact(int fd, const StaticString &data, unsigned long long *timeout = NULL);
303
+
196
304
  /**
197
305
  * Writes a bunch of data to the given file descriptor using a gathering I/O interface.
198
306
  * Instead of accepting a single buffer, this function accepts multiple buffers plus
@@ -248,6 +356,15 @@ void gatheredWrite(int fd, const StaticString data[], unsigned int dataCount)
248
356
  */
249
357
  void setWritevFunction(WritevFunction func);
250
358
 
359
+ /**
360
+ * Closes the given file descriptor and throws an exception if anything goes wrong.
361
+ * This function also works around certain close() bugs on certain operating systems.
362
+ *
363
+ * @throws SystemException
364
+ * @throws boost::thread_interrupted
365
+ */
366
+ void safelyClose(int fd);
367
+
251
368
  } // namespace Passenger
252
369
 
253
370
  #endif /* _PASSENGER_IO_UTILS_H_ */