passenger 2.0.6 → 2.1.2

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 (497) hide show
  1. data/DEVELOPERS.TXT +10 -4
  2. data/LICENSE +1 -1
  3. data/NEWS +0 -0
  4. data/Rakefile +183 -117
  5. data/benchmark/dispatcher.rb +5 -9
  6. data/bin/passenger-install-apache2-module +52 -18
  7. data/bin/passenger-memory-stats +67 -13
  8. data/bin/passenger-spawn-server +8 -4
  9. data/bin/passenger-status +21 -46
  10. data/bin/passenger-stress-test +5 -5
  11. data/debian/postinst +1 -1
  12. data/doc/ApplicationPool algorithm.txt +180 -128
  13. data/doc/Architectural overview.html +1 -778
  14. data/doc/Security of user switching support.html +1 -643
  15. data/doc/Users guide Apache.html +3127 -0
  16. data/doc/Users guide Nginx.html +1458 -0
  17. data/doc/Users guide.html +1404 -467
  18. data/doc/Users guide.txt +843 -105
  19. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +751 -641
  20. data/doc/cxxapi/ApplicationPool_8h-source.html +168 -171
  21. data/doc/cxxapi/Application_8h-source.html +494 -394
  22. data/doc/cxxapi/Bucket_8h-source.html +21 -15
  23. data/doc/cxxapi/CachedFileStat_8h-source.html +191 -0
  24. data/doc/cxxapi/Configuration_8h-source.html +311 -149
  25. data/doc/cxxapi/DirectoryMapper_8h-source.html +309 -0
  26. data/doc/cxxapi/DummySpawnManager_8h-source.html +3 -4
  27. data/doc/cxxapi/Exceptions_8h-source.html +182 -165
  28. data/doc/cxxapi/FileChecker_8h-source.html +130 -0
  29. data/doc/cxxapi/Hooks_8h-source.html +2 -3
  30. data/doc/cxxapi/Logging_8h-source.html +92 -89
  31. data/doc/cxxapi/MessageChannel_8h-source.html +585 -477
  32. data/doc/cxxapi/PoolOptions_8h-source.html +305 -0
  33. data/doc/cxxapi/SpawnManager_8h-source.html +515 -540
  34. data/doc/cxxapi/StandardApplicationPool_8h-source.html +779 -679
  35. data/doc/cxxapi/SystemTime_8h-source.html +104 -0
  36. data/doc/cxxapi/Utils_8h-source.html +331 -227
  37. data/doc/cxxapi/annotated.html +6 -7
  38. data/doc/cxxapi/classClient-members.html +1 -2
  39. data/doc/cxxapi/classClient.html +1 -2
  40. data/doc/cxxapi/classHooks-members.html +5 -2
  41. data/doc/cxxapi/classHooks.html +112 -2
  42. data/doc/cxxapi/classPassenger_1_1Application-members.html +2 -3
  43. data/doc/cxxapi/classPassenger_1_1Application.html +8 -9
  44. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +4 -4
  45. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +42 -81
  46. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +1 -2
  47. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +3 -4
  48. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
  49. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +3 -2
  50. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +74 -3
  51. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +1 -2
  52. data/doc/cxxapi/classPassenger_1_1BusyException.html +2 -3
  53. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +1 -2
  54. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +2 -3
  55. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +38 -0
  56. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +256 -0
  57. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +1 -2
  58. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +2 -3
  59. data/doc/cxxapi/{classPassenger_1_1Thread-members.html → classPassenger_1_1FileChecker-members.html} +4 -5
  60. data/doc/cxxapi/classPassenger_1_1FileChecker.html +121 -0
  61. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +1 -2
  62. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +2 -3
  63. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
  64. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +2 -3
  65. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +2 -3
  66. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
  67. data/doc/cxxapi/classPassenger_1_1IOException-members.html +1 -2
  68. data/doc/cxxapi/classPassenger_1_1IOException.html +2 -3
  69. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
  70. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +5 -2
  71. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +155 -5
  72. data/doc/cxxapi/{classboost_1_1this__thread_1_1enable__syscall__interruption-members.html → classPassenger_1_1RuntimeException-members.html} +2 -3
  73. data/doc/cxxapi/{classboost_1_1this__thread_1_1enable__syscall__interruption.html → classPassenger_1_1RuntimeException.html} +10 -8
  74. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +1 -2
  75. data/doc/cxxapi/classPassenger_1_1SpawnException.html +2 -3
  76. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +2 -3
  77. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +15 -56
  78. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +5 -4
  79. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +20 -81
  80. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
  81. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +2 -3
  82. data/doc/cxxapi/classPassenger_1_1SystemException.html +9 -10
  83. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
  84. data/doc/cxxapi/{classboost_1_1this__thread_1_1disable__syscall__interruption-members.html → classPassenger_1_1SystemTime-members.html} +5 -3
  85. data/doc/cxxapi/classPassenger_1_1SystemTime.html +86 -0
  86. data/doc/cxxapi/classPassenger_1_1TempFile-members.html +2 -3
  87. data/doc/cxxapi/classPassenger_1_1TempFile.html +17 -9
  88. data/doc/cxxapi/definitions_8h-source.html +1 -2
  89. data/doc/cxxapi/files.html +6 -3
  90. data/doc/cxxapi/functions.html +98 -35
  91. data/doc/cxxapi/functions_func.html +60 -32
  92. data/doc/cxxapi/functions_type.html +1 -2
  93. data/doc/cxxapi/functions_vars.html +27 -2
  94. data/doc/cxxapi/graph_legend.html +1 -2
  95. data/doc/cxxapi/graph_legend.png +0 -0
  96. data/doc/cxxapi/group__Configuration.html +3 -4
  97. data/doc/cxxapi/group__Configuration.png +0 -0
  98. data/doc/cxxapi/group__Core.html +3 -4
  99. data/doc/cxxapi/group__Core.png +0 -0
  100. data/doc/cxxapi/group__Exceptions.html +4 -2
  101. data/doc/cxxapi/group__Hooks.html +1 -6
  102. data/doc/cxxapi/group__Hooks.png +0 -0
  103. data/doc/cxxapi/group__Support.html +259 -36
  104. data/doc/cxxapi/hierarchy.html +6 -7
  105. data/doc/cxxapi/inherit__graph__0.map +1 -1
  106. data/doc/cxxapi/inherit__graph__0.md5 +1 -1
  107. data/doc/cxxapi/inherit__graph__0.png +0 -0
  108. data/doc/cxxapi/inherit__graph__1.map +1 -1
  109. data/doc/cxxapi/inherit__graph__1.md5 +1 -1
  110. data/doc/cxxapi/inherit__graph__1.png +0 -0
  111. data/doc/cxxapi/inherit__graph__10.map +1 -1
  112. data/doc/cxxapi/inherit__graph__10.md5 +1 -1
  113. data/doc/cxxapi/inherit__graph__10.png +0 -0
  114. data/doc/cxxapi/inherit__graph__11.map +1 -1
  115. data/doc/cxxapi/inherit__graph__11.md5 +1 -1
  116. data/doc/cxxapi/inherit__graph__11.png +0 -0
  117. data/doc/cxxapi/inherit__graph__12.map +2 -1
  118. data/doc/cxxapi/inherit__graph__12.md5 +1 -1
  119. data/doc/cxxapi/inherit__graph__12.png +0 -0
  120. data/doc/cxxapi/inherit__graph__13.map +1 -1
  121. data/doc/cxxapi/inherit__graph__13.md5 +1 -1
  122. data/doc/cxxapi/inherit__graph__13.png +0 -0
  123. data/doc/cxxapi/inherit__graph__14.map +1 -2
  124. data/doc/cxxapi/inherit__graph__14.md5 +1 -1
  125. data/doc/cxxapi/inherit__graph__14.png +0 -0
  126. data/doc/cxxapi/inherit__graph__15.map +1 -1
  127. data/doc/cxxapi/inherit__graph__15.md5 +1 -1
  128. data/doc/cxxapi/inherit__graph__15.png +0 -0
  129. data/doc/cxxapi/inherit__graph__16.map +1 -1
  130. data/doc/cxxapi/inherit__graph__16.md5 +1 -1
  131. data/doc/cxxapi/inherit__graph__16.png +0 -0
  132. data/doc/cxxapi/inherit__graph__17.png +0 -0
  133. data/doc/cxxapi/inherit__graph__18.png +0 -0
  134. data/doc/cxxapi/inherit__graph__19.png +0 -0
  135. data/doc/cxxapi/inherit__graph__2.map +1 -1
  136. data/doc/cxxapi/inherit__graph__2.md5 +1 -1
  137. data/doc/cxxapi/inherit__graph__2.png +0 -0
  138. data/doc/cxxapi/inherit__graph__20.map +1 -1
  139. data/doc/cxxapi/inherit__graph__20.md5 +1 -1
  140. data/doc/cxxapi/inherit__graph__20.png +0 -0
  141. data/doc/cxxapi/inherit__graph__21.map +1 -1
  142. data/doc/cxxapi/inherit__graph__21.md5 +1 -1
  143. data/doc/cxxapi/inherit__graph__21.png +0 -0
  144. data/doc/cxxapi/inherit__graph__3.map +1 -1
  145. data/doc/cxxapi/inherit__graph__3.md5 +1 -1
  146. data/doc/cxxapi/inherit__graph__3.png +0 -0
  147. data/doc/cxxapi/inherit__graph__4.map +1 -1
  148. data/doc/cxxapi/inherit__graph__4.md5 +1 -1
  149. data/doc/cxxapi/inherit__graph__4.png +0 -0
  150. data/doc/cxxapi/inherit__graph__5.map +2 -1
  151. data/doc/cxxapi/inherit__graph__5.md5 +1 -1
  152. data/doc/cxxapi/inherit__graph__5.png +0 -0
  153. data/doc/cxxapi/inherit__graph__6.map +1 -1
  154. data/doc/cxxapi/inherit__graph__6.md5 +1 -1
  155. data/doc/cxxapi/inherit__graph__6.png +0 -0
  156. data/doc/cxxapi/inherit__graph__7.map +1 -1
  157. data/doc/cxxapi/inherit__graph__7.md5 +1 -1
  158. data/doc/cxxapi/inherit__graph__7.png +0 -0
  159. data/doc/cxxapi/inherit__graph__8.map +1 -1
  160. data/doc/cxxapi/inherit__graph__8.md5 +1 -1
  161. data/doc/cxxapi/inherit__graph__8.png +0 -0
  162. data/doc/cxxapi/inherit__graph__9.map +1 -2
  163. data/doc/cxxapi/inherit__graph__9.md5 +1 -1
  164. data/doc/cxxapi/inherit__graph__9.png +0 -0
  165. data/doc/cxxapi/inherits.html +30 -31
  166. data/doc/cxxapi/main.html +1 -2
  167. data/doc/cxxapi/modules.html +1 -2
  168. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +1 -2
  169. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +2 -3
  170. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +1 -2
  171. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +2 -3
  172. data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +49 -0
  173. data/doc/cxxapi/structPassenger_1_1PoolOptions.html +404 -0
  174. data/doc/cxxapi/tree.html +18 -20
  175. data/doc/images/conservative_spawning.png +0 -0
  176. data/doc/images/conservative_spawning.svg +248 -0
  177. data/doc/images/smart-lv2.png +0 -0
  178. data/doc/images/smart-lv2.svg +320 -0
  179. data/doc/rdoc/classes/ConditionVariable.html +68 -34
  180. data/doc/rdoc/classes/Exception.html +16 -16
  181. data/doc/rdoc/classes/GC.html +9 -9
  182. data/doc/rdoc/classes/IO.html +36 -17
  183. data/doc/rdoc/classes/PhusionPassenger.html +183 -0
  184. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +511 -0
  185. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer.html +285 -242
  186. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerAlreadyStarted.html +3 -3
  187. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerError.html +3 -3
  188. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerNotStarted.html +3 -3
  189. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/UnknownMessage.html +3 -3
  190. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +598 -0
  191. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +140 -0
  192. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +247 -0
  193. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +138 -0
  194. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AppInitError.html +36 -19
  195. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/Application.html +81 -96
  196. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/ConsoleTextTemplate.html +18 -18
  197. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/FrameworkInitError.html +20 -18
  198. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/HTMLTemplate.html +18 -18
  199. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/InitializationError.html +9 -9
  200. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +92 -0
  201. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/MessageChannel.html +93 -92
  202. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/NativeSupport.html +55 -25
  203. data/doc/rdoc/classes/PhusionPassenger/Rack.html +91 -0
  204. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +185 -0
  205. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +182 -0
  206. data/doc/rdoc/classes/PhusionPassenger/Railz.html +95 -0
  207. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +424 -0
  208. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +98 -0
  209. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +200 -0
  210. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +444 -0
  211. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +98 -0
  212. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +154 -0
  213. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +408 -0
  214. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/UnknownError.html +13 -13
  215. data/doc/rdoc/classes/PhusionPassenger/Utils.html +687 -0
  216. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/VersionNotFound.html +8 -8
  217. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +89 -0
  218. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +188 -0
  219. data/doc/rdoc/classes/PlatformInfo.html +663 -159
  220. data/doc/rdoc/classes/RakeExtensions.html +4 -4
  221. data/doc/rdoc/classes/Signal.html +134 -0
  222. data/doc/rdoc/created.rid +1 -1
  223. data/doc/rdoc/files/DEVELOPERS_TXT.html +15 -10
  224. data/doc/rdoc/files/README.html +5 -7
  225. data/doc/rdoc/files/ext/{passenger → phusion_passenger}/native_support_c.html +2 -2
  226. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/abstract_request_handler_rb.html +7 -9
  227. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +120 -0
  228. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/abstract_server_rb.html +7 -10
  229. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +99 -0
  230. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +92 -0
  231. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/application_rb.html +6 -8
  232. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/console_text_template_rb.html +5 -7
  233. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/constants_rb.html +4 -5
  234. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/dependencies_rb.html +6 -8
  235. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +116 -0
  236. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/exceptions_rb.html +5 -7
  237. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/html_template_rb.html +5 -7
  238. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/message_channel_rb.html +5 -7
  239. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/platform_info_rb.html +6 -7
  240. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +123 -0
  241. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +117 -0
  242. data/doc/rdoc/files/lib/{passenger/utils_rb.html → phusion_passenger/railz/application_spawner_rb.html} +24 -17
  243. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +126 -0
  244. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +139 -0
  245. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +118 -0
  246. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/simple_benchmarking_rb.html +5 -7
  247. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/spawn_manager_rb.html +40 -24
  248. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +169 -0
  249. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +120 -0
  250. data/doc/rdoc/files/lib/rake/extensions_rb.html +3 -4
  251. data/doc/rdoc/fr_class_index.html +37 -19
  252. data/doc/rdoc/fr_file_index.html +25 -14
  253. data/doc/rdoc/fr_method_index.html +145 -74
  254. data/ext/apache2/Application.h +145 -44
  255. data/ext/apache2/ApplicationPool.h +27 -29
  256. data/ext/apache2/ApplicationPoolServer.h +183 -72
  257. data/ext/apache2/ApplicationPoolServerExecutable.cpp +249 -42
  258. data/ext/apache2/Bucket.cpp +61 -9
  259. data/ext/apache2/Bucket.h +15 -8
  260. data/ext/apache2/CachedFileStat.cpp +114 -0
  261. data/ext/apache2/CachedFileStat.h +169 -0
  262. data/ext/apache2/Configuration.cpp +213 -22
  263. data/ext/apache2/Configuration.h +176 -13
  264. data/ext/apache2/DirectoryMapper.h +287 -0
  265. data/ext/apache2/Exceptions.h +30 -12
  266. data/ext/apache2/FileChecker.h +108 -0
  267. data/ext/apache2/Hooks.cpp +709 -493
  268. data/ext/apache2/LICENSE-CNRI.TXT +15 -0
  269. data/ext/apache2/Logging.h +26 -22
  270. data/ext/apache2/MessageChannel.h +124 -15
  271. data/ext/apache2/PoolOptions.h +283 -0
  272. data/ext/apache2/SpawnManager.h +75 -99
  273. data/ext/apache2/StandardApplicationPool.h +296 -195
  274. data/ext/apache2/SystemTime.cpp +28 -0
  275. data/ext/apache2/SystemTime.h +82 -0
  276. data/ext/apache2/Utils.cpp +172 -18
  277. data/ext/apache2/Utils.h +124 -19
  278. data/ext/boost/cstdint.hpp +4 -2
  279. data/ext/boost/current_function.hpp +67 -0
  280. data/ext/boost/detail/sp_counted_base.hpp +4 -4
  281. data/ext/boost/thread/exceptions.hpp +2 -1
  282. data/ext/boost/thread/pthread/thread.hpp +11 -3
  283. data/ext/boost/thread/pthread/thread_data.hpp +2 -1
  284. data/ext/oxt/backtrace.cpp +172 -0
  285. data/ext/oxt/backtrace.hpp +135 -0
  286. data/ext/oxt/detail/backtrace_disabled.hpp +39 -0
  287. data/ext/oxt/detail/backtrace_enabled.hpp +155 -0
  288. data/ext/oxt/detail/spin_lock_gcc_x86.hpp +82 -0
  289. data/ext/oxt/detail/spin_lock_portable.hpp +38 -0
  290. data/ext/oxt/detail/spin_lock_pthreads.hpp +97 -0
  291. data/ext/oxt/detail/tracable_exception_disabled.hpp +46 -0
  292. data/ext/oxt/detail/tracable_exception_enabled.hpp +48 -0
  293. data/ext/oxt/macros.hpp +58 -0
  294. data/ext/oxt/spin_lock.hpp +55 -0
  295. data/ext/{apache2/System.cpp → oxt/system_calls.cpp} +87 -52
  296. data/ext/oxt/system_calls.hpp +234 -0
  297. data/ext/oxt/thread.cpp +32 -0
  298. data/ext/oxt/thread.hpp +223 -0
  299. data/ext/oxt/tracable_exception.cpp +87 -0
  300. data/ext/oxt/tracable_exception.hpp +35 -0
  301. data/{lib/passenger/constants.rb → ext/phusion_passenger/extconf.rb} +14 -9
  302. data/ext/{passenger → phusion_passenger}/native_support.c +33 -6
  303. data/lib/{passenger → phusion_passenger}/abstract_request_handler.rb +209 -93
  304. data/lib/{passenger → phusion_passenger}/abstract_server.rb +23 -8
  305. data/lib/phusion_passenger/abstract_server_collection.rb +301 -0
  306. data/lib/phusion_passenger/admin_tools.rb +25 -0
  307. data/lib/phusion_passenger/admin_tools/control_process.rb +107 -0
  308. data/lib/{passenger → phusion_passenger}/application.rb +13 -16
  309. data/lib/{passenger → phusion_passenger}/console_text_template.rb +2 -2
  310. data/{ext/passenger/extconf.rb → lib/phusion_passenger/constants.rb} +5 -5
  311. data/lib/{passenger → phusion_passenger}/dependencies.rb +38 -32
  312. data/lib/phusion_passenger/events.rb +45 -0
  313. data/lib/{passenger → phusion_passenger}/exceptions.rb +12 -5
  314. data/lib/{passenger → phusion_passenger}/html_template.rb +2 -2
  315. data/lib/{passenger → phusion_passenger}/message_channel.rb +3 -2
  316. data/lib/phusion_passenger/platform_info.rb +500 -0
  317. data/lib/{passenger → phusion_passenger}/rack/application_spawner.rb +29 -22
  318. data/lib/{passenger → phusion_passenger}/rack/request_handler.rb +14 -9
  319. data/lib/{passenger → phusion_passenger}/railz/application_spawner.rb +94 -74
  320. data/lib/{passenger → phusion_passenger}/railz/cgi_fixed.rb +2 -2
  321. data/lib/{passenger → phusion_passenger}/railz/framework_spawner.rb +86 -98
  322. data/lib/{passenger → phusion_passenger}/railz/request_handler.rb +6 -6
  323. data/lib/{passenger → phusion_passenger}/simple_benchmarking.rb +0 -0
  324. data/lib/{passenger → phusion_passenger}/spawn_manager.rb +136 -128
  325. data/lib/{passenger → phusion_passenger}/templates/apache2_config_snippets.txt.erb +0 -0
  326. data/lib/{passenger → phusion_passenger}/templates/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
  327. data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +38 -0
  328. data/lib/{passenger → phusion_passenger}/templates/app_init_error.html.erb +0 -0
  329. data/lib/{passenger → phusion_passenger}/templates/database_error.html.erb +0 -0
  330. data/lib/{passenger → phusion_passenger}/templates/deployment_example.txt.erb +1 -1
  331. data/lib/{passenger → phusion_passenger}/templates/error_layout.css +0 -0
  332. data/lib/{passenger → phusion_passenger}/templates/error_layout.html.erb +0 -0
  333. data/lib/{passenger → phusion_passenger}/templates/framework_init_error.html.erb +0 -0
  334. data/lib/{passenger → phusion_passenger}/templates/general_error.html.erb +0 -0
  335. data/lib/{passenger → phusion_passenger}/templates/invalid_app_root.html.erb +1 -1
  336. data/lib/{passenger → phusion_passenger}/templates/load_error.html.erb +0 -0
  337. data/lib/{passenger → phusion_passenger}/templates/no_write_permission_to_passenger_root.txt.erb +0 -0
  338. data/lib/{passenger → phusion_passenger}/templates/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
  339. data/lib/{passenger → phusion_passenger}/templates/run_installer_as_root.txt.erb +0 -0
  340. data/lib/{passenger → phusion_passenger}/templates/version_not_found.html.erb +0 -0
  341. data/lib/{passenger → phusion_passenger}/templates/welcome.txt.erb +0 -0
  342. data/lib/{passenger → phusion_passenger}/utils.rb +210 -44
  343. data/lib/{passenger → phusion_passenger}/wsgi/application_spawner.rb +18 -15
  344. data/lib/{passenger → phusion_passenger}/wsgi/request_handler.py +7 -1
  345. data/man/passenger-memory-stats.8 +1 -1
  346. data/misc/render_error_pages.rb +1 -1
  347. data/test/ApplicationPoolServerTest.cpp +0 -28
  348. data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +4 -0
  349. data/test/ApplicationPoolTest.cpp +307 -69
  350. data/test/CachedFileStatTest.cpp +262 -0
  351. data/test/FileCheckerTest.cpp +79 -0
  352. data/test/MessageChannelTest.cpp +3 -3
  353. data/test/PoolOptionsTest.cpp +37 -0
  354. data/test/SpawnManagerTest.cpp +4 -4
  355. data/test/StandardApplicationPoolTest.cpp +4 -0
  356. data/test/SystemTimeTest.cpp +37 -0
  357. data/test/UtilsTest.cpp +137 -0
  358. data/test/integration_tests.rb +270 -23
  359. data/test/oxt/backtrace_test.cpp +128 -0
  360. data/test/oxt/oxt_test_main.cpp +25 -0
  361. data/test/oxt/syscall_interruption_test.cpp +50 -0
  362. data/test/ruby/abstract_request_handler_spec.rb +83 -0
  363. data/test/ruby/abstract_server_collection_spec.rb +246 -0
  364. data/test/ruby/application_spec.rb +3 -3
  365. data/test/ruby/message_channel_spec.rb +2 -2
  366. data/test/ruby/rack/application_spawner_spec.rb +3 -5
  367. data/test/ruby/rails/application_spawner_spec.rb +54 -15
  368. data/test/ruby/rails/framework_spawner_spec.rb +6 -8
  369. data/test/ruby/rails/minimal_spawner_spec.rb +29 -0
  370. data/test/ruby/rails/spawner_error_handling_spec.rb +1 -1
  371. data/test/ruby/rails/spawner_privilege_lowering_spec.rb +3 -3
  372. data/test/ruby/spawn_manager_spec.rb +23 -12
  373. data/test/ruby/utils_spec.rb +36 -2
  374. data/test/ruby/wsgi/application_spawner_spec.rb +47 -0
  375. data/test/stub/apache2/httpd.conf.erb +3 -5
  376. data/test/stub/message_channel.rb +2 -2
  377. data/test/stub/message_channel_2.rb +2 -2
  378. data/test/stub/message_channel_3.rb +3 -3
  379. data/test/stub/minimal-railsapp/README +0 -0
  380. data/test/stub/minimal-railsapp/config/application.rb +0 -0
  381. data/test/stub/minimal-railsapp/config/environment.rb +0 -0
  382. data/test/stub/minimal-railsapp/vendor/rails/actionmailer/lib/action_mailer.rb +0 -0
  383. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_controller.rb +0 -0
  384. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_pack.rb +0 -0
  385. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_view.rb +0 -0
  386. data/test/stub/minimal-railsapp/vendor/rails/activerecord/lib/active_record.rb +0 -0
  387. data/test/stub/minimal-railsapp/vendor/rails/activeresource/lib/active_resource.rb +0 -0
  388. data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support.rb +0 -0
  389. data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support/whiny_nil.rb +0 -0
  390. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/dispatcher.rb +0 -0
  391. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/initializer.rb +0 -0
  392. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/ruby_version_check.rb +0 -0
  393. data/test/stub/rails_apps/foobar/app/controllers/foo_controller.rb +8 -0
  394. data/test/stub/rails_apps/foobar/config/environments/development.rb +1 -2
  395. data/test/stub/rails_apps/mycook/app/controllers/welcome_controller.rb +21 -1
  396. data/test/stub/rails_apps/mycook/sites/some.site/public/uploads.html +26 -0
  397. data/test/stub/rails_apps/mycook/sites/some.site/public/welcome/cached.html +26 -0
  398. data/test/stub/railsapp/app/controllers/application.rb +0 -0
  399. data/test/stub/railsapp/app/controllers/bar_controller_1.rb +0 -0
  400. data/test/stub/railsapp/app/controllers/bar_controller_2.rb +1 -1
  401. data/test/stub/railsapp/app/controllers/foo_controller.rb +4 -0
  402. data/test/stub/railsapp/app/helpers/application_helper.rb +0 -0
  403. data/test/stub/railsapp/config/boot.rb +0 -0
  404. data/test/stub/railsapp/config/database.yml +0 -0
  405. data/test/stub/railsapp/config/environment.rb +0 -0
  406. data/test/stub/railsapp/config/environments/development.rb +0 -0
  407. data/test/stub/railsapp/config/environments/production.rb +0 -0
  408. data/test/stub/railsapp/config/initializers/inflections.rb +0 -0
  409. data/test/stub/railsapp/config/initializers/mime_types.rb +0 -0
  410. data/test/stub/railsapp/config/routes.rb +0 -0
  411. data/test/stub/railsapp/public/useless.txt +0 -0
  412. data/test/stub/spawn_server.rb +3 -4
  413. data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
  414. data/test/support/apache2_controller.rb +57 -7
  415. data/test/support/tut.h +15 -0
  416. data/vendor/README +12 -0
  417. data/vendor/README_FOR_PACKAGERS +1 -0
  418. data/vendor/rack-0.9.1/AUTHORS +8 -0
  419. data/vendor/rack-0.9.1/COPYING +18 -0
  420. data/vendor/rack-0.9.1/ChangeLog +1423 -0
  421. data/vendor/rack-0.9.1/KNOWN-ISSUES +18 -0
  422. data/vendor/rack-0.9.1/README +306 -0
  423. data/vendor/rack-0.9.1/Rakefile +188 -0
  424. data/vendor/rack-0.9.1/SPEC +129 -0
  425. data/vendor/rack-0.9.1/lib/rack.rb +86 -0
  426. data/vendor/rack-0.9.1/lib/rack/adapter/camping.rb +22 -0
  427. data/vendor/rack-0.9.1/lib/rack/auth/abstract/handler.rb +28 -0
  428. data/vendor/rack-0.9.1/lib/rack/auth/abstract/request.rb +37 -0
  429. data/vendor/rack-0.9.1/lib/rack/auth/basic.rb +58 -0
  430. data/vendor/rack-0.9.1/lib/rack/auth/digest/md5.rb +124 -0
  431. data/vendor/rack-0.9.1/lib/rack/auth/digest/nonce.rb +51 -0
  432. data/vendor/rack-0.9.1/lib/rack/auth/digest/params.rb +55 -0
  433. data/vendor/rack-0.9.1/lib/rack/auth/digest/request.rb +40 -0
  434. data/vendor/rack-0.9.1/lib/rack/auth/openid.rb +438 -0
  435. data/vendor/rack-0.9.1/lib/rack/builder.rb +67 -0
  436. data/vendor/rack-0.9.1/lib/rack/cascade.rb +36 -0
  437. data/vendor/rack-0.9.1/lib/rack/commonlogger.rb +61 -0
  438. data/vendor/rack-0.9.1/lib/rack/conditionalget.rb +43 -0
  439. data/vendor/rack-0.9.1/lib/rack/content_length.rb +25 -0
  440. data/vendor/rack-0.9.1/lib/rack/deflater.rb +87 -0
  441. data/vendor/rack-0.9.1/lib/rack/directory.rb +150 -0
  442. data/vendor/rack-0.9.1/lib/rack/file.rb +85 -0
  443. data/vendor/rack-0.9.1/lib/rack/handler.rb +48 -0
  444. data/vendor/rack-0.9.1/lib/rack/handler/cgi.rb +57 -0
  445. data/vendor/rack-0.9.1/lib/rack/handler/evented_mongrel.rb +8 -0
  446. data/vendor/rack-0.9.1/lib/rack/handler/fastcgi.rb +86 -0
  447. data/vendor/rack-0.9.1/lib/rack/handler/lsws.rb +52 -0
  448. data/vendor/rack-0.9.1/lib/rack/handler/mongrel.rb +82 -0
  449. data/vendor/rack-0.9.1/lib/rack/handler/scgi.rb +57 -0
  450. data/vendor/rack-0.9.1/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  451. data/vendor/rack-0.9.1/lib/rack/handler/thin.rb +15 -0
  452. data/vendor/rack-0.9.1/lib/rack/handler/webrick.rb +61 -0
  453. data/vendor/rack-0.9.1/lib/rack/head.rb +19 -0
  454. data/vendor/rack-0.9.1/lib/rack/lint.rb +465 -0
  455. data/vendor/rack-0.9.1/lib/rack/lobster.rb +65 -0
  456. data/vendor/rack-0.9.1/lib/rack/methodoverride.rb +27 -0
  457. data/vendor/rack-0.9.1/lib/rack/mime.rb +204 -0
  458. data/vendor/rack-0.9.1/lib/rack/mock.rb +160 -0
  459. data/vendor/rack-0.9.1/lib/rack/recursive.rb +57 -0
  460. data/vendor/rack-0.9.1/lib/rack/reloader.rb +64 -0
  461. data/vendor/rack-0.9.1/lib/rack/request.rb +218 -0
  462. data/vendor/rack-0.9.1/lib/rack/response.rb +171 -0
  463. data/vendor/rack-0.9.1/lib/rack/session/abstract/id.rb +153 -0
  464. data/vendor/rack-0.9.1/lib/rack/session/cookie.rb +89 -0
  465. data/vendor/rack-0.9.1/lib/rack/session/memcache.rb +97 -0
  466. data/vendor/rack-0.9.1/lib/rack/session/pool.rb +73 -0
  467. data/vendor/rack-0.9.1/lib/rack/showexceptions.rb +348 -0
  468. data/vendor/rack-0.9.1/lib/rack/showstatus.rb +106 -0
  469. data/vendor/rack-0.9.1/lib/rack/static.rb +38 -0
  470. data/vendor/rack-0.9.1/lib/rack/urlmap.rb +48 -0
  471. data/vendor/rack-0.9.1/lib/rack/utils.rb +347 -0
  472. metadata +1197 -1055
  473. data/doc/cxxapi/System_8h-source.html +0 -251
  474. data/doc/cxxapi/classDirectoryMapper-members.html +0 -38
  475. data/doc/cxxapi/classDirectoryMapper.html +0 -203
  476. data/doc/cxxapi/classPassenger_1_1Thread.html +0 -100
  477. data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption.html +0 -46
  478. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption-members.html +0 -33
  479. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption.html +0 -44
  480. data/doc/cxxapi/namespacePassenger.html +0 -208
  481. data/doc/cxxapi/namespacePassenger_1_1InterruptableCalls.html +0 -43
  482. data/doc/cxxapi/namespacemembers.html +0 -70
  483. data/doc/cxxapi/namespacemembers_func.html +0 -66
  484. data/doc/cxxapi/namespacemembers_type.html +0 -46
  485. data/doc/cxxapi/namespaces.html +0 -35
  486. data/doc/rdoc/classes/Passenger.html +0 -136
  487. data/doc/rdoc/classes/Passenger/AbstractRequestHandler.html +0 -402
  488. data/doc/rdoc/classes/Passenger/SpawnManager.html +0 -379
  489. data/doc/rdoc/classes/Passenger/Utils.html +0 -578
  490. data/ext/apache2/System.h +0 -228
  491. data/lib/passenger/platform_info.rb +0 -302
  492. data/lib/passenger/templates/app_exited_during_initialization.html.erb +0 -19
  493. data/test/stub/apache2/httpd.conf +0 -75
  494. data/test/stub/rails_apps/foobar/config/environments/test.rb +0 -22
  495. data/test/stub/rails_apps/mycook/config/environments/test.rb +0 -22
  496. data/test/stub/railsapp/config/environments/test.rb +0 -22
  497. data/test/stub/railsapp2/config/environments/test.rb +0 -22
@@ -18,9 +18,9 @@
18
18
 
19
19
  require 'socket'
20
20
  require 'fcntl'
21
- require 'passenger/utils'
22
- require 'passenger/native_support'
23
- module Passenger
21
+ require 'phusion_passenger/message_channel'
22
+ require 'phusion_passenger/utils'
23
+ module PhusionPassenger
24
24
 
25
25
  # The request handler is the layer which connects Apache with the underlying application's
26
26
  # request dispatcher (i.e. either Rails's Dispatcher class or Rack).
@@ -39,30 +39,20 @@ module Passenger
39
39
  # administrator maintenance overhead. These decisions are documented
40
40
  # in this section.
41
41
  #
42
- # === Abstract namespace Unix sockets
43
- #
44
- # AbstractRequestHandler listens on a Unix socket for incoming requests. If possible,
45
- # AbstractRequestHandler will try to create a Unix socket on the _abstract namespace_,
46
- # instead of on the filesystem. If the RoR application crashes (segfault),
47
- # or if it gets killed by SIGKILL, or if the system loses power, then there
48
- # will be no stale socket files left on the filesystem.
49
- # Unfortunately, abstract namespace Unix sockets are only supported by Linux.
50
- # On systems that do not support abstract namespace Unix sockets,
51
- # AbstractRequestHandler will automatically fallback to using regular Unix socket files.
52
- #
53
- # It is possible to force AbstractRequestHandler to use regular Unix socket files by
54
- # setting the environment variable PASSENGER_NO_ABSTRACT_NAMESPACE_SOCKETS
55
- # to 1.
56
- #
57
42
  # === Owner pipes
58
43
  #
59
44
  # Because only the web server communicates directly with a request handler,
60
45
  # we want the request handler to exit if the web server has also exited.
61
46
  # This is implemented by using a so-called _owner pipe_. The writable part
62
- # of the pipe will be owned by the web server. AbstractRequestHandler will
63
- # continuously check whether the other side of the pipe has been closed. If
64
- # so, then it knows that the web server has exited, and so the request handler
65
- # will exit as well. This works even if the web server gets killed by SIGKILL.
47
+ # of the pipe will be passed to the web server* via a Unix socket, and the web
48
+ # server will own that part of the pipe, while AbstractRequestHandler owns
49
+ # the readable part of the pipe. AbstractRequestHandler will continuously
50
+ # check whether the other side of the pipe has been closed. If so, then it
51
+ # knows that the web server has exited, and so the request handler will exit
52
+ # as well. This works even if the web server gets killed by SIGKILL.
53
+ #
54
+ # * It might also be passed to the ApplicationPoolServerExecutable, if the web
55
+ # server's using ApplicationPoolServer instead of StandardApplicationPool.
66
56
  #
67
57
  #
68
58
  # == Request format
@@ -94,7 +84,7 @@ class AbstractRequestHandler
94
84
  HARD_TERMINATION_SIGNAL = "SIGTERM"
95
85
  # Signal which will cause the Rails application to exit as soon as it's done processing a request.
96
86
  SOFT_TERMINATION_SIGNAL = "SIGUSR1"
97
- BACKLOG_SIZE = 50
87
+ BACKLOG_SIZE = 100
98
88
  MAX_HEADER_SIZE = 128 * 1024
99
89
 
100
90
  # String constants which exist to relieve Ruby's garbage collector.
@@ -104,72 +94,117 @@ class AbstractRequestHandler
104
94
  CONTENT_LENGTH = 'CONTENT_LENGTH' # :nodoc:
105
95
  HTTP_CONTENT_LENGTH = 'HTTP_CONTENT_LENGTH' # :nodoc:
106
96
  X_POWERED_BY = 'X-Powered-By' # :nodoc:
97
+ REQUEST_METHOD = 'REQUEST_METHOD' # :nodoc:
98
+ PING = 'ping' # :nodoc:
107
99
 
108
100
  # The name of the socket on which the request handler accepts
109
- # new connections. This is either a Unix socket filename, or
110
- # the name for an abstract namespace Unix socket.
101
+ # new connections. At this moment, this value is always the filename
102
+ # of a Unix domain socket.
111
103
  #
112
- # If +socket_name+ refers to an abstract namespace Unix socket,
113
- # then the name does _not_ contain a leading null byte.
114
- #
115
- # See also using_abstract_namespace?
104
+ # See also #socket_type.
116
105
  attr_reader :socket_name
117
-
106
+
107
+ # The type of socket that #socket_name refers to. At the moment, the
108
+ # value is always 'unix', which indicates a Unix domain socket.
109
+ attr_reader :socket_type
110
+
111
+ # Specifies the maximum allowed memory usage, in MB. If after having processed
112
+ # a request AbstractRequestHandler detects that memory usage has risen above
113
+ # this limit, then it will gracefully exit (that is, exit after having processed
114
+ # all pending requests).
115
+ #
116
+ # A value of 0 (the default) indicates that there's no limit.
117
+ attr_accessor :memory_limit
118
+
119
+ # The number of times the main loop has iterated so far. Mostly useful
120
+ # for unit test assertions.
121
+ attr_reader :iterations
122
+
123
+ # Number of requests processed so far. This includes requests that raised
124
+ # exceptions.
125
+ attr_reader :processed_requests
126
+
118
127
  # Create a new RequestHandler with the given owner pipe.
119
128
  # +owner_pipe+ must be the readable part of a pipe IO object.
120
- def initialize(owner_pipe)
121
- if abstract_namespace_sockets_allowed?
122
- @using_abstract_namespace = create_unix_socket_on_abstract_namespace
123
- else
124
- @using_abstract_namespace = false
125
- end
126
- if !@using_abstract_namespace
129
+ #
130
+ # Additionally, the following options may be given:
131
+ # - memory_limit: Used to set the +memory_limit+ attribute.
132
+ def initialize(owner_pipe, options = {})
133
+ if should_use_unix_sockets?
127
134
  create_unix_socket_on_filesystem
135
+ else
136
+ create_tcp_socket
128
137
  end
129
- @socket.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
138
+ @socket.close_on_exec!
130
139
  @owner_pipe = owner_pipe
131
140
  @previous_signal_handlers = {}
141
+ @main_loop_thread_lock = Mutex.new
142
+ @main_loop_thread_cond = ConditionVariable.new
143
+ @memory_limit = options["memory_limit"] || 0
144
+ @iterations = 0
145
+ @processed_requests = 0
132
146
  end
133
147
 
134
148
  # Clean up temporary stuff created by the request handler.
135
- # This method should be called after the main loop has exited.
149
+ #
150
+ # If the main loop was started by #main_loop, then this method may only
151
+ # be called after the main loop has exited.
152
+ #
153
+ # If the main loop was started by #start_main_loop_thread, then this method
154
+ # may be called at any time, and it will stop the main loop thread.
136
155
  def cleanup
156
+ if @main_loop_thread
157
+ @main_loop_thread.raise(Interrupt.new("Cleaning up"))
158
+ @main_loop_thread.join
159
+ end
137
160
  @socket.close rescue nil
138
161
  @owner_pipe.close rescue nil
139
- if !using_abstract_namespace?
140
- File.unlink(@socket_name) rescue nil
141
- end
162
+ File.unlink(@socket_name) rescue nil
142
163
  end
143
164
 
144
- # Returns whether socket_name refers to an abstract namespace Unix socket.
145
- def using_abstract_namespace?
146
- return @using_abstract_namespace
165
+ # Check whether the main loop's currently running.
166
+ def main_loop_running?
167
+ return @main_loop_running
147
168
  end
148
169
 
149
170
  # Enter the request handler's main loop.
150
171
  def main_loop
151
172
  reset_signal_handlers
152
173
  begin
153
- done = false
154
- while !done
174
+ @graceful_termination_pipe = IO.pipe
175
+ @graceful_termination_pipe[0].close_on_exec!
176
+ @graceful_termination_pipe[1].close_on_exec!
177
+
178
+ @main_loop_thread_lock.synchronize do
179
+ @main_loop_running = true
180
+ @main_loop_thread_cond.broadcast
181
+ end
182
+
183
+ install_useful_signal_handlers
184
+
185
+ while true
186
+ @iterations += 1
155
187
  client = accept_connection
156
188
  if client.nil?
157
189
  break
158
190
  end
159
- trap SOFT_TERMINATION_SIGNAL do
160
- done = true
161
- end
162
191
  begin
163
192
  headers, input = parse_request(client)
164
193
  if headers
165
- process_request(headers, input, client)
194
+ if headers[REQUEST_METHOD] == PING
195
+ process_ping(headers, input, client)
196
+ else
197
+ process_request(headers, input, client)
198
+ end
166
199
  end
167
200
  rescue IOError, SocketError, SystemCallError => e
168
201
  print_exception("Passenger RequestHandler", e)
169
202
  ensure
203
+ # 'input' is the same as 'client' so we don't
204
+ # need to close that.
170
205
  client.close rescue nil
171
206
  end
172
- trap SOFT_TERMINATION_SIGNAL, DEFAULT
207
+ @processed_requests += 1
173
208
  end
174
209
  rescue EOFError
175
210
  # Exit main loop.
@@ -181,47 +216,54 @@ class AbstractRequestHandler
181
216
  raise
182
217
  end
183
218
  ensure
219
+ @graceful_termination_pipe[0].close rescue nil
220
+ @graceful_termination_pipe[1].close rescue nil
184
221
  revert_signal_handlers
222
+ @main_loop_thread_lock.synchronize do
223
+ @main_loop_running = false
224
+ @main_loop_thread_cond.broadcast
225
+ end
185
226
  end
186
227
  end
187
-
188
- private
189
- include Utils
190
-
191
- def create_unix_socket_on_abstract_namespace
192
- while true
193
- begin
194
- # I have no idea why, but using base64-encoded IDs
195
- # don't pass the unit tests. I couldn't find the cause
196
- # of the problem. The system supports base64-encoded
197
- # names for abstract namespace unix sockets just fine.
198
- @socket_name = generate_random_id(:hex)
199
- @socket_name = @socket_name.slice(0, NativeSupport::UNIX_PATH_MAX - 2)
200
- fd = NativeSupport.create_unix_socket("\x00#{socket_name}", BACKLOG_SIZE)
201
- @socket = IO.new(fd)
202
- @socket.instance_eval do
203
- def accept
204
- fd = NativeSupport.accept(fileno)
205
- return IO.new(fd)
206
- end
207
- end
208
- return true
209
- rescue Errno::EADDRINUSE
210
- # Do nothing, try again with another name.
211
- rescue Errno::ENOENT
212
- # Abstract namespace sockets not supported on this system.
213
- return false
228
+
229
+ # Start the main loop in a new thread. This thread will be stopped by #cleanup.
230
+ def start_main_loop_thread
231
+ @main_loop_thread = Thread.new do
232
+ main_loop
233
+ end
234
+ @main_loop_thread_lock.synchronize do
235
+ while !@main_loop_running
236
+ @main_loop_thread_cond.wait(@main_loop_thread_lock)
214
237
  end
215
238
  end
216
239
  end
240
+
241
+ private
242
+ include Utils
217
243
 
244
+ def should_use_unix_sockets?
245
+ # There seems to be a bug in MacOS X w.r.t. Unix sockets.
246
+ # When the Unix socket subsystem is under high stress, a
247
+ # recv()/read() on a Unix socket can return 0 even when EOF is
248
+ # not reached. We work around this by using TCP sockets on
249
+ # MacOS X.
250
+ return RUBY_PLATFORM !~ /darwin/
251
+ end
252
+
218
253
  def create_unix_socket_on_filesystem
219
254
  done = false
220
255
  while !done
221
256
  begin
222
- @socket_name = "/tmp/passenger.#{generate_random_id(:base64)}"
223
- @socket_name = @socket_name.slice(0, NativeSupport::UNIX_PATH_MAX - 1)
257
+ if defined?(NativeSupport)
258
+ unix_path_max = NativeSupport::UNIX_PATH_MAX
259
+ else
260
+ unix_path_max = 100
261
+ end
262
+ @socket_name = "#{passenger_tmpdir}/passenger_backend.#{generate_random_id(:base64)}"
263
+ @socket_name = @socket_name.slice(0, unix_path_max - 1)
224
264
  @socket = UNIXServer.new(@socket_name)
265
+ @socket.listen(BACKLOG_SIZE)
266
+ @socket_type = "unix"
225
267
  File.chmod(0600, @socket_name)
226
268
  done = true
227
269
  rescue Errno::EADDRINUSE
@@ -229,12 +271,21 @@ private
229
271
  end
230
272
  end
231
273
  end
274
+
275
+ def create_tcp_socket
276
+ # We use "127.0.0.1" as address in order to force
277
+ # TCPv4 instead of TCPv6.
278
+ @socket = TCPServer.new('127.0.0.1', 0)
279
+ @socket.listen(BACKLOG_SIZE)
280
+ @socket_name = "127.0.0.1:#{@socket.addr[1]}"
281
+ @socket_type = "tcp"
282
+ end
232
283
 
233
284
  # Reset signal handlers to their default handler, and install some
234
285
  # special handlers for a few signals. The previous signal handlers
235
286
  # will be put back by calling revert_signal_handlers.
236
287
  def reset_signal_handlers
237
- Signal.list.each_key do |signal|
288
+ Signal.list_trappable.each_key do |signal|
238
289
  begin
239
290
  prev_handler = trap(signal, DEFAULT)
240
291
  if prev_handler != DEFAULT
@@ -245,9 +296,45 @@ private
245
296
  end
246
297
  end
247
298
  trap('HUP', IGNORE)
299
+ end
300
+
301
+ def install_useful_signal_handlers
302
+ trappable_signals = Signal.list_trappable
303
+
304
+ trap(SOFT_TERMINATION_SIGNAL) do
305
+ @graceful_termination_pipe[1].close rescue nil
306
+ end if trappable_signals.has_key?(SOFT_TERMINATION_SIGNAL.sub(/^SIG/, ''))
307
+
248
308
  trap('ABRT') do
249
309
  raise SignalException, "SIGABRT"
250
- end
310
+ end if trappable_signals.has_key?('ABRT')
311
+
312
+ trap('QUIT') do
313
+ if Kernel.respond_to?(:caller_for_all_threads)
314
+ output = "========== Process #{Process.pid}: backtrace dump ==========\n"
315
+ caller_for_all_threads.each_pair do |thread, stack|
316
+ output << ("-" * 60) << "\n"
317
+ output << "# Thread: #{thread.inspect}, "
318
+ if thread == Thread.main
319
+ output << "[main thread], "
320
+ else
321
+ output << "[current thread], "
322
+ end
323
+ output << "alive = #{thread.alive?}\n"
324
+ output << ("-" * 60) << "\n"
325
+ output << " " << stack.join("\n ")
326
+ output << "\n\n"
327
+ end
328
+ else
329
+ output = "========== Process #{Process.pid}: backtrace dump ==========\n"
330
+ output << ("-" * 60) << "\n"
331
+ output << "# Current thread: #{Thread.current.inspect}\n"
332
+ output << ("-" * 60) << "\n"
333
+ output << " " << caller.join("\n ")
334
+ end
335
+ STDERR.puts(output)
336
+ STDERR.flush
337
+ end if trappable_signals.has_key?('QUIT')
251
338
  end
252
339
 
253
340
  def revert_signal_handlers
@@ -257,10 +344,38 @@ private
257
344
  end
258
345
 
259
346
  def accept_connection
260
- ios = select([@socket, @owner_pipe])[0]
347
+ ios = select([@socket, @owner_pipe, @graceful_termination_pipe[0]]).first
261
348
  if ios.include?(@socket)
262
349
  client = @socket.accept
263
- client.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
350
+ client.close_on_exec!
351
+
352
+ # Some people report that sometimes their Ruby (MRI/REE)
353
+ # processes get stuck with 100% CPU usage. Upon further
354
+ # inspection with strace, it turns out that these Ruby
355
+ # processes are continuously calling lseek() on a socket,
356
+ # which of course returns ESPIPE as error. gdb reveals
357
+ # lseek() is called by fwrite(), which in turn is called
358
+ # by rb_fwrite(). The affected socket is the
359
+ # AbstractRequestHandler client socket.
360
+ #
361
+ # I inspected the MRI source code and didn't find
362
+ # anything that would explain this behavior. This makes
363
+ # me think that it's a glibc bug, but that's very
364
+ # unlikely.
365
+ #
366
+ # The rb_fwrite() implementation takes an entirely
367
+ # different code path if I set 'sync' to true: it will
368
+ # skip fwrite() and use write() instead. So here we set
369
+ # 'sync' to true in the hope that this will work around
370
+ # the problem.
371
+ client.sync = true
372
+
373
+ # We monkeypatch the 'sync=' method to a no-op so that
374
+ # sync mode can't be disabled.
375
+ client.instance_eval do
376
+ def client.sync=(value)
377
+ end
378
+ end
264
379
 
265
380
  # The real input stream is not seekable (calling _seek_
266
381
  # or _rewind_ on it will raise an exception). But some
@@ -274,8 +389,10 @@ private
274
389
 
275
390
  return client
276
391
  else
277
- # The other end of the pipe has been closed.
278
- # So we know all owning processes have quit.
392
+ # The other end of the owner pipe has been closed, or the
393
+ # graceful termination pipe has been closed. This is our
394
+ # call to gracefully terminate (after having processed all
395
+ # incoming requests).
279
396
  return nil
280
397
  end
281
398
  end
@@ -301,6 +418,10 @@ private
301
418
  print_exception("Passenger RequestHandler", e)
302
419
  end
303
420
 
421
+ def process_ping(env, input, output)
422
+ output.write("pong")
423
+ end
424
+
304
425
  # Generate a long, cryptographically secure random ID string, which
305
426
  # is also a valid filename.
306
427
  def generate_random_id(method)
@@ -318,11 +439,6 @@ private
318
439
  return data
319
440
  end
320
441
 
321
- def abstract_namespace_sockets_allowed?
322
- return !ENV['PASSENGER_NO_ABSTRACT_NAMESPACE_SOCKETS'] ||
323
- ENV['PASSENGER_NO_ABSTRACT_NAMESPACE_SOCKETS'].empty?
324
- end
325
-
326
442
  def self.determine_passenger_version
327
443
  rakefile = "#{File.dirname(__FILE__)}/../../Rakefile"
328
444
  if File.exist?(rakefile)
@@ -347,4 +463,4 @@ public
347
463
  PASSENGER_HEADER = determine_passenger_header
348
464
  end
349
465
 
350
- end # module Passenger
466
+ end # module PhusionPassenger
@@ -19,10 +19,9 @@
19
19
  require 'socket'
20
20
  require 'set'
21
21
  require 'timeout'
22
- require 'passenger/message_channel'
23
- require 'passenger/utils'
24
- require 'passenger/native_support'
25
- module Passenger
22
+ require 'phusion_passenger/message_channel'
23
+ require 'phusion_passenger/utils'
24
+ module PhusionPassenger
26
25
 
27
26
  # An abstract base class for a server, with the following properties:
28
27
  #
@@ -43,7 +42,7 @@ module Passenger
43
42
  #
44
43
  # Here's an example on using AbstractServer:
45
44
  #
46
- # class MyServer < Passenger::AbstractServer
45
+ # class MyServer < PhusionPassenger::AbstractServer
47
46
  # def initialize
48
47
  # super()
49
48
  # define_message_handler(:hello, :handle_hello)
@@ -88,11 +87,25 @@ class AbstractServer
88
87
  class ServerError < StandardError
89
88
  end
90
89
 
90
+ # The last time when this AbstractServer had processed a message.
91
+ attr_accessor :last_activity_time
92
+
93
+ # The maximum time that this AbstractServer may be idle. Used by
94
+ # AbstractServerCollection to determine when this object should
95
+ # be cleaned up. nil or 0 indicate that this object should never
96
+ # be idle cleaned.
97
+ attr_accessor :max_idle_time
98
+
99
+ # Used by AbstractServerCollection to remember when this AbstractServer
100
+ # should be idle cleaned.
101
+ attr_accessor :next_cleaning_time
102
+
91
103
  def initialize
92
104
  @done = false
93
105
  @message_handlers = {}
94
106
  @signal_handlers = {}
95
107
  @orig_signal_handlers = {}
108
+ @last_activity_time = Time.now
96
109
  end
97
110
 
98
111
  # Start the server. This method does not block since the server runs
@@ -109,7 +122,8 @@ class AbstractServer
109
122
 
110
123
  @parent_socket, @child_socket = UNIXSocket.pair
111
124
  before_fork
112
- @pid = fork do
125
+ @pid = fork
126
+ if @pid.nil?
113
127
  begin
114
128
  STDOUT.sync = true
115
129
  STDERR.sync = true
@@ -278,7 +292,7 @@ private
278
292
  # Reset all signal handlers to default. This is called in the child process,
279
293
  # before entering the main loop.
280
294
  def reset_signal_handlers
281
- Signal.list.each_key do |signal|
295
+ Signal.list_trappable.each_key do |signal|
282
296
  begin
283
297
  @orig_signal_handlers[signal] = trap(signal, 'DEFAULT')
284
298
  rescue ArgumentError
@@ -311,6 +325,7 @@ private
311
325
  while !@done
312
326
  begin
313
327
  name, *args = channel.read
328
+ @last_activity_time = Time.now
314
329
  if name.nil?
315
330
  @done = true
316
331
  elsif @message_handlers.has_key?(name)
@@ -331,4 +346,4 @@ private
331
346
  end
332
347
  end
333
348
 
334
- end # module Passenger
349
+ end # module PhusionPassenger