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
@@ -14,14 +14,17 @@
14
14
  # with this program; if not, write to the Free Software Foundation, Inc.,
15
15
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
16
 
17
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../../../vendor/rack-0.9.1/lib"))
17
18
  require 'rack'
19
+
18
20
  require 'socket'
19
- require 'passenger/application'
20
- require 'passenger/message_channel'
21
- require 'passenger/abstract_request_handler'
22
- require 'passenger/utils'
23
- require 'passenger/rack/request_handler'
24
- module Passenger
21
+ require 'phusion_passenger/application'
22
+ require 'phusion_passenger/message_channel'
23
+ require 'phusion_passenger/abstract_request_handler'
24
+ require 'phusion_passenger/utils'
25
+ require 'phusion_passenger/rack/request_handler'
26
+
27
+ module PhusionPassenger
25
28
  module Rack
26
29
 
27
30
  # Class for spawning Rack applications.
@@ -41,14 +44,18 @@ class ApplicationSpawner
41
44
  # - AppInitError: The Rack application raised an exception or called
42
45
  # exit() during startup.
43
46
  # - SystemCallError, IOError, SocketError: Something went wrong.
44
- def spawn_application(app_root, lower_privilege = true, lowest_user = "nobody", environment = "production")
47
+ def spawn_application(app_root, options = {})
48
+ options = sanitize_spawn_options(options)
49
+
45
50
  a, b = UNIXSocket.pair
46
- # Double fork in order to prevent zombie processes.
47
- pid = safe_fork(self.class.to_s) do
48
- safe_fork(self.class.to_s) do
49
- a.close
50
- run(MessageChannel.new(b), app_root, lower_privilege, lowest_user, environment)
51
- end
51
+ pid = safe_fork(self.class.to_s, true) do
52
+ a.close
53
+
54
+ file_descriptors_to_leave_open = [0, 1, 2, b.fileno]
55
+ NativeSupport.close_all_file_descriptors(file_descriptors_to_leave_open)
56
+ close_all_io_objects_for_fds(file_descriptors_to_leave_open)
57
+
58
+ run(MessageChannel.new(b), app_root, options)
52
59
  end
53
60
  b.close
54
61
  Process.waitpid(pid) rescue nil
@@ -57,25 +64,25 @@ class ApplicationSpawner
57
64
  unmarshal_and_raise_errors(channel, "rack")
58
65
 
59
66
  # No exception was raised, so spawning succeeded.
60
- pid, socket_name, using_abstract_namespace = channel.read
67
+ pid, socket_name, socket_type = channel.read
61
68
  if pid.nil?
62
69
  raise IOError, "Connection closed"
63
70
  end
64
71
  owner_pipe = channel.recv_io
65
72
  return Application.new(@app_root, pid, socket_name,
66
- using_abstract_namespace == "true", owner_pipe)
73
+ socket_type, owner_pipe)
67
74
  end
68
75
 
69
76
  private
70
77
 
71
- def run(channel, app_root, lower_privilege, lowest_user, environment)
78
+ def run(channel, app_root, options)
72
79
  $0 = "Rack: #{app_root}"
73
80
  app = nil
74
81
  success = report_app_init_status(channel) do
75
- ENV['RACK_ENV'] = environment
82
+ ENV['RACK_ENV'] = options["environment"]
76
83
  Dir.chdir(app_root)
77
- if lower_privilege
78
- lower_privilege('config.ru', lowest_user)
84
+ if options["lower_privilege"]
85
+ lower_privilege('config.ru', options["lowest_user"])
79
86
  end
80
87
  app = load_rack_app
81
88
  end
@@ -83,9 +90,9 @@ private
83
90
  if success
84
91
  reader, writer = IO.pipe
85
92
  begin
86
- handler = RequestHandler.new(reader, app)
93
+ handler = RequestHandler.new(reader, app, options)
87
94
  channel.write(Process.pid, handler.socket_name,
88
- handler.using_abstract_namespace?)
95
+ handler.socket_type)
89
96
  channel.send_io(writer)
90
97
  writer.close
91
98
  channel.close
@@ -105,4 +112,4 @@ private
105
112
  end
106
113
 
107
114
  end # module Rack
108
- end # module Passenger
115
+ end # module PhusionPassenger
@@ -14,8 +14,8 @@
14
14
  # with this program; if not, write to the Free Software Foundation, Inc.,
15
15
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
16
 
17
- require 'passenger/abstract_request_handler'
18
- module Passenger
17
+ require 'phusion_passenger/abstract_request_handler'
18
+ module PhusionPassenger
19
19
  module Rack
20
20
 
21
21
  # A request handler for Rack applications.
@@ -40,8 +40,8 @@ class RequestHandler < AbstractRequestHandler
40
40
  CRLF = "\r\n" # :nodoc:
41
41
 
42
42
  # +app+ is the Rack application object.
43
- def initialize(owner_pipe, app)
44
- super(owner_pipe)
43
+ def initialize(owner_pipe, app, options = {})
44
+ super(owner_pipe, options)
45
45
  @app = app
46
46
  end
47
47
 
@@ -66,13 +66,18 @@ protected
66
66
  begin
67
67
  output.write("Status: #{status}#{CRLF}")
68
68
  headers[X_POWERED_BY] = PASSENGER_HEADER
69
- headers.each do |k, vs|
70
- vs.each do |v|
71
- output.write("#{k}: #{v}#{CRLF}")
69
+ headers.each_pair do |key, values|
70
+ if values.is_a?(String)
71
+ values = values.split("\n")
72
+ end
73
+ values.each do |value|
74
+ output.write("#{key}: #{value}#{CRLF}")
72
75
  end
73
76
  end
74
77
  output.write(CRLF)
75
- if body
78
+ if body.is_a?(String)
79
+ output.write(body)
80
+ elsif body
76
81
  body.each do |s|
77
82
  output.write(s)
78
83
  end
@@ -84,4 +89,4 @@ protected
84
89
  end
85
90
 
86
91
  end # module Rack
87
- end # module Passenger
92
+ end # module PhusionPassenger
@@ -20,15 +20,17 @@ require 'rubygems'
20
20
  require 'socket'
21
21
  require 'etc'
22
22
  require 'fcntl'
23
- require 'passenger/application'
24
- require 'passenger/abstract_server'
25
- require 'passenger/application'
26
- require 'passenger/rack/request_handler'
27
- require 'passenger/railz/request_handler'
28
- require 'passenger/exceptions'
29
- require 'passenger/utils'
23
+ require 'phusion_passenger/application'
24
+ require 'phusion_passenger/abstract_server'
25
+ require 'phusion_passenger/application'
26
+ require 'phusion_passenger/constants'
27
+ require 'phusion_passenger/events'
28
+ require 'phusion_passenger/railz/request_handler'
29
+ require 'phusion_passenger/rack/request_handler'
30
+ require 'phusion_passenger/exceptions'
31
+ require 'phusion_passenger/utils'
30
32
 
31
- module Passenger
33
+ module PhusionPassenger
32
34
  module Railz
33
35
 
34
36
  # This class is capable of spawning instances of a single Ruby on Rails application.
@@ -53,41 +55,45 @@ class ApplicationSpawner < AbstractServer
53
55
  # The group ID of the root user.
54
56
  ROOT_GID = 0
55
57
 
56
- # An attribute, used internally. This should not be used outside Passenger.
57
- attr_accessor :time
58
58
  # The application root of this spawner.
59
59
  attr_reader :app_root
60
60
 
61
61
  # +app_root+ is the root directory of this application, i.e. the directory
62
62
  # that contains 'app/', 'public/', etc. If given an invalid directory,
63
63
  # or a directory that doesn't appear to be a Rails application root directory,
64
- # then an ArgumentError will be raised.
64
+ # then an InvalidPath will be raised.
65
65
  #
66
- # If +lower_privilege+ is true, then ApplicationSpawner will attempt to
67
- # switch to the user who owns the application's <tt>config/environment.rb</tt>,
68
- # and to the default group of that user.
66
+ # Additional options are:
67
+ # - +lower_privilege+ and +lowest_user+:
68
+ # If +lower_privilege+ is true, then ApplicationSpawner will attempt to
69
+ # switch to the user who owns the application's <tt>config/environment.rb</tt>,
70
+ # and to the default group of that user.
69
71
  #
70
- # If that user doesn't exist on the system, or if that user is root,
71
- # then ApplicationSpawner will attempt to switch to the username given by
72
- # +lowest_user+ (and to the default group of that user).
73
- # If +lowest_user+ doesn't exist either, or if switching user failed
74
- # (because the current process does not have the privilege to do so),
75
- # then ApplicationSpawner will continue without reporting an error.
72
+ # If that user doesn't exist on the system, or if that user is root,
73
+ # then ApplicationSpawner will attempt to switch to the username given by
74
+ # +lowest_user+ (and to the default group of that user).
75
+ # If +lowest_user+ doesn't exist either, or if switching user failed
76
+ # (because the current process does not have the privilege to do so),
77
+ # then ApplicationSpawner will continue without reporting an error.
76
78
  #
77
- # The +environment+ argument allows one to specify the RAILS_ENV environment to use.
78
- def initialize(app_root, lower_privilege = true, lowest_user = "nobody", environment = "production")
79
+ # - +environment+:
80
+ # Allows one to specify the RAILS_ENV environment to use.
81
+ #
82
+ # All other options will be passed on to RequestHandler.
83
+ def initialize(app_root, options = {})
79
84
  super()
80
85
  begin
81
86
  @app_root = normalize_path(app_root)
82
87
  rescue SystemCallError => e
83
- raise ArgumentError, e.message
84
- rescue ArgumentError
88
+ raise InvalidPath, e.message
89
+ rescue InvalidPath
85
90
  raise
86
91
  end
87
- @lower_privilege = lower_privilege
88
- @lowest_user = lowest_user
89
- @environment = environment
90
- self.time = Time.now
92
+ @options = sanitize_spawn_options(options)
93
+ @lower_privilege = @options["lower_privilege"]
94
+ @lowest_user = @options["lowest_user"]
95
+ @environment = @options["environment"]
96
+ self.max_idle_time = DEFAULT_APP_SPAWNER_MAX_IDLE_TIME
91
97
  assert_valid_app_root(@app_root)
92
98
  define_message_handler(:spawn_application, :handle_spawn_application)
93
99
  end
@@ -100,15 +106,15 @@ class ApplicationSpawner < AbstractServer
100
106
  # - ApplicationSpawner::Error: The ApplicationSpawner server exited unexpectedly.
101
107
  def spawn_application
102
108
  server.write("spawn_application")
103
- pid, socket_name, using_abstract_namespace = server.read
109
+ pid, socket_name, socket_type = server.read
104
110
  if pid.nil?
105
111
  raise IOError, "Connection closed"
106
112
  end
107
113
  owner_pipe = server.recv_io
108
114
  return Application.new(@app_root, pid, socket_name,
109
- using_abstract_namespace == "true", owner_pipe)
115
+ socket_type, owner_pipe)
110
116
  rescue SystemCallError, IOError, SocketError => e
111
- raise Error, "The application spawner server exited unexpectedly"
117
+ raise Error, "The application spawner server exited unexpectedly: #{e}"
112
118
  end
113
119
 
114
120
  # Spawn an instance of the RoR application. When successful, an Application object
@@ -126,30 +132,37 @@ class ApplicationSpawner < AbstractServer
126
132
  # or called exit() during startup.
127
133
  # - SystemCallError, IOError, SocketError: Something went wrong.
128
134
  def spawn_application!
129
- # Double fork to prevent zombie processes.
130
135
  a, b = UNIXSocket.pair
131
- pid = safe_fork(self.class.to_s) do
132
- safe_fork('application') do
133
- begin
134
- a.close
135
- channel = MessageChannel.new(b)
136
- success = report_app_init_status(channel) do
137
- ENV['RAILS_ENV'] = @environment
138
- Dir.chdir(@app_root)
139
- if @lower_privilege
140
- lower_privilege('config/environment.rb', @lowest_user)
141
- end
142
- require 'config/environment'
143
- require 'dispatcher'
144
- end
145
- if success
146
- start_request_handler(channel)
147
- end
148
- rescue SignalException => e
149
- if e.message != AbstractRequestHandler::HARD_TERMINATION_SIGNAL &&
150
- e.message != AbstractRequestHandler::SOFT_TERMINATION_SIGNAL
151
- raise
136
+ pid = safe_fork('application', true) do
137
+ begin
138
+ a.close
139
+
140
+ file_descriptors_to_leave_open = [0, 1, 2, b.fileno]
141
+ NativeSupport.close_all_file_descriptors(file_descriptors_to_leave_open)
142
+ close_all_io_objects_for_fds(file_descriptors_to_leave_open)
143
+
144
+ channel = MessageChannel.new(b)
145
+ success = report_app_init_status(channel) do
146
+ ENV['RAILS_ENV'] = @environment
147
+ Dir.chdir(@app_root)
148
+ if @lower_privilege
149
+ lower_privilege('config/environment.rb', @lowest_user)
152
150
  end
151
+
152
+ # require Rails' environment, using the same path as the original rails dispatcher,
153
+ # which normally does: require File.dirname(__FILE__) + "/../config/environment"
154
+ # thus avoiding the possibility of including the same file twice.
155
+ require 'public/../config/environment'
156
+
157
+ require 'dispatcher'
158
+ end
159
+ if success
160
+ start_request_handler(channel, false)
161
+ end
162
+ rescue SignalException => e
163
+ if e.message != AbstractRequestHandler::HARD_TERMINATION_SIGNAL &&
164
+ e.message != AbstractRequestHandler::SOFT_TERMINATION_SIGNAL
165
+ raise
153
166
  end
154
167
  end
155
168
  end
@@ -160,13 +173,13 @@ class ApplicationSpawner < AbstractServer
160
173
  unmarshal_and_raise_errors(channel)
161
174
 
162
175
  # No exception was raised, so spawning succeeded.
163
- pid, socket_name, using_abstract_namespace = channel.read
176
+ pid, socket_name, socket_type = channel.read
164
177
  if pid.nil?
165
178
  raise IOError, "Connection closed"
166
179
  end
167
180
  owner_pipe = channel.recv_io
168
181
  return Application.new(@app_root, pid, socket_name,
169
- using_abstract_namespace == "true", owner_pipe)
182
+ socket_type, owner_pipe)
170
183
  end
171
184
 
172
185
  # Overrided from AbstractServer#start.
@@ -179,9 +192,9 @@ class ApplicationSpawner < AbstractServer
179
192
  super
180
193
  begin
181
194
  unmarshal_and_raise_errors(server)
182
- rescue IOError, SystemCallError, SocketError
195
+ rescue IOError, SystemCallError, SocketError => e
183
196
  stop
184
- raise Error, "The application spawner server exited unexpectedly"
197
+ raise Error, "The application spawner server exited unexpectedly: #{e}"
185
198
  rescue
186
199
  stop
187
200
  raise
@@ -267,7 +280,12 @@ private
267
280
  else
268
281
  require_dependency 'application'
269
282
  end
270
- if GC.copy_on_write_friendly?
283
+
284
+ # - No point in preloading the application sources if the garbage collector
285
+ # isn't copy-on-write friendly.
286
+ # - Rails >= 2.2 already preloads application sources by default, so no need
287
+ # to do that again.
288
+ if GC.copy_on_write_friendly? && !::Rails::Initializer.respond_to?(:load_application_classes)
271
289
  Dir.glob('app/{models,controllers,helpers}/*.rb').each do |file|
272
290
  require_dependency normalize_path(file)
273
291
  end
@@ -275,25 +293,24 @@ private
275
293
  end
276
294
 
277
295
  def handle_spawn_application
278
- # Double fork to prevent zombie processes.
279
- pid = safe_fork(self.class.to_s) do
280
- safe_fork('application') do
281
- begin
282
- start_request_handler(client)
283
- rescue SignalException => e
284
- if e.message != AbstractRequestHandler::HARD_TERMINATION_SIGNAL &&
285
- e.message != AbstractRequestHandler::SOFT_TERMINATION_SIGNAL
286
- raise
287
- end
296
+ safe_fork('application', true) do
297
+ begin
298
+ start_request_handler(client, true)
299
+ rescue SignalException => e
300
+ if e.message != AbstractRequestHandler::HARD_TERMINATION_SIGNAL &&
301
+ e.message != AbstractRequestHandler::SOFT_TERMINATION_SIGNAL
302
+ raise
288
303
  end
289
304
  end
290
305
  end
291
- Process.waitpid(pid)
292
306
  end
293
307
 
294
308
  # Initialize the request handler and enter its main loop.
295
309
  # Spawn information will be sent back via _channel_.
296
- def start_request_handler(channel)
310
+ # The _forked_ argument indicates whether a new process was forked off
311
+ # after loading environment.rb (i.e. whether smart spawning is being
312
+ # used).
313
+ def start_request_handler(channel, forked)
297
314
  $0 = "Rails: #{@app_root}"
298
315
  reader, writer = IO.pipe
299
316
  begin
@@ -308,24 +325,27 @@ private
308
325
 
309
326
  if Rails::VERSION::STRING >= '2.3.0'
310
327
  rack_app = ::ActionController::Dispatcher.new
311
- handler = Rack::RequestHandler.new(reader, rack_app)
328
+ handler = Rack::RequestHandler.new(reader, rack_app, @options)
312
329
  else
313
- handler = RequestHandler.new(reader)
330
+ handler = RequestHandler.new(reader, @options)
314
331
  end
315
332
 
316
333
  channel.write(Process.pid, handler.socket_name,
317
- handler.using_abstract_namespace?)
334
+ handler.socket_type)
318
335
  channel.send_io(writer)
319
336
  writer.close
320
337
  channel.close
338
+
339
+ PhusionPassenger.call_event(:starting_worker_process, forked)
321
340
  handler.main_loop
322
341
  ensure
323
342
  channel.close rescue nil
324
343
  writer.close rescue nil
325
344
  handler.cleanup rescue nil
345
+ PhusionPassenger.call_event(:stopping_worker_process)
326
346
  end
327
347
  end
328
348
  end
329
349
 
330
350
  end # module Railz
331
- end # module Passenger
351
+ end # module PhusionPassenger
@@ -26,7 +26,7 @@
26
26
 
27
27
  require 'cgi'
28
28
 
29
- module Passenger
29
+ module PhusionPassenger
30
30
  module Railz
31
31
 
32
32
  # Modifies CGI so that we can use it. Main thing it does is expose
@@ -65,4 +65,4 @@ class CGIFixed < ::CGI
65
65
  end
66
66
 
67
67
  end # module Railz
68
- end # module Passenger
68
+ end # module PhusionPassenger
@@ -17,12 +17,13 @@
17
17
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
 
19
19
  require 'rubygems'
20
- require 'passenger/abstract_server'
21
- require 'passenger/railz/application_spawner'
22
- require 'passenger/exceptions'
23
- require 'passenger/constants'
24
- require 'passenger/utils'
25
- module Passenger
20
+ require 'phusion_passenger/abstract_server'
21
+ require 'phusion_passenger/abstract_server_collection'
22
+ require 'phusion_passenger/railz/application_spawner'
23
+ require 'phusion_passenger/exceptions'
24
+ require 'phusion_passenger/constants'
25
+ require 'phusion_passenger/utils'
26
+ module PhusionPassenger
26
27
  module Railz
27
28
 
28
29
  # This class is capable of spawning Ruby on Rails application instances
@@ -45,12 +46,9 @@ class FrameworkSpawner < AbstractServer
45
46
  class Error < AbstractServer::ServerError
46
47
  end
47
48
 
48
- # An attribute, used internally. This should not be used outside Passenger.
49
- attr_accessor :time
50
-
51
49
  # Creates a new instance of FrameworkSpawner.
52
50
  #
53
- # Valid options:
51
+ # Valid options are:
54
52
  # - <tt>:version</tt>: The Ruby on Rails version to use. It is not checked whether
55
53
  # this version is actually installed.
56
54
  # - <tt>:vendor</tt>: The directory to the vendor Rails framework to use. This is
@@ -58,6 +56,8 @@ class FrameworkSpawner < AbstractServer
58
56
  #
59
57
  # It is not allowed to specify both +version+ and +vendor+.
60
58
  #
59
+ # All other options will be passed on to ApplicationSpawner and RequestHandler.
60
+ #
61
61
  # Note that the specified Rails framework will be loaded during the entire life time
62
62
  # of the FrameworkSpawner server. If you wish to reload the Rails framework's code,
63
63
  # then restart the server by calling AbstractServer#stop and AbstractServer#start.
@@ -66,7 +66,7 @@ class FrameworkSpawner < AbstractServer
66
66
  raise ArgumentError, "The 'options' argument not seem to be an options hash"
67
67
  end
68
68
  @version = options[:version]
69
- @vendor = options[:vendor]
69
+ @vendor = options[:vendor]
70
70
  if !@version && !@vendor
71
71
  raise ArgumentError, "Either the 'version' or the 'vendor' option must specified"
72
72
  elsif @version && @vendor
@@ -74,6 +74,7 @@ class FrameworkSpawner < AbstractServer
74
74
  end
75
75
 
76
76
  super()
77
+ self.max_idle_time = DEFAULT_FRAMEWORK_SPAWNER_MAX_IDLE_TIME
77
78
  define_message_handler(:spawn_application, :handle_spawn_application)
78
79
  define_message_handler(:reload, :handle_reload)
79
80
  end
@@ -86,7 +87,12 @@ class FrameworkSpawner < AbstractServer
86
87
  def start
87
88
  super
88
89
  begin
89
- status = server.read[0]
90
+ result = server.read
91
+ if result.nil?
92
+ raise Error, "The framework spawner server exited unexpectedly."
93
+ else
94
+ status = result[0]
95
+ end
90
96
  if status == 'exception'
91
97
  child_exception = unmarshal_exception(server.read_scalar)
92
98
  stop
@@ -111,8 +117,23 @@ class FrameworkSpawner < AbstractServer
111
117
  # When successful, an Application object will be returned, which represents
112
118
  # the spawned RoR application.
113
119
  #
114
- # See ApplicationSpawner.new for an explanation of the +lower_privilege+,
115
- # +lowest_user+ and +environment+ parameters.
120
+ # The following options are allowed:
121
+ # - +lower_privilege+ and +lowest_user+:
122
+ # If +lower_privilege+ is true, then ApplicationSpawner will attempt to
123
+ # switch to the user who owns the application's <tt>config/environment.rb</tt>,
124
+ # and to the default group of that user.
125
+ #
126
+ # If that user doesn't exist on the system, or if that user is root,
127
+ # then ApplicationSpawner will attempt to switch to the username given by
128
+ # +lowest_user+ (and to the default group of that user).
129
+ # If +lowest_user+ doesn't exist either, or if switching user failed
130
+ # (because the current process does not have the privilege to do so),
131
+ # then ApplicationSpawner will continue without reporting an error.
132
+ #
133
+ # - +environment+:
134
+ # Allows one to specify the RAILS_ENV environment to use.
135
+ #
136
+ # All other options will be passed on to ApplicationSpawner and RequestHandler.
116
137
  #
117
138
  # FrameworkSpawner will internally cache the code of applications, in order to
118
139
  # speed up future spawning attempts. This implies that, if you've changed
@@ -122,30 +143,37 @@ class FrameworkSpawner < AbstractServer
122
143
  #
123
144
  # Raises:
124
145
  # - AbstractServer::ServerNotStarted: The FrameworkSpawner server hasn't already been started.
125
- # - ArgumentError: +app_root+ doesn't appear to be a valid Ruby on Rails application root.
146
+ # - InvalidAppRoot: +app_root+ doesn't appear to be a valid Ruby on Rails application root.
126
147
  # - AppInitError: The application raised an exception or called exit() during startup.
127
148
  # - ApplicationSpawner::Error: The ApplicationSpawner server exited unexpectedly.
128
149
  # - FrameworkSpawner::Error: The FrameworkSpawner server exited unexpectedly.
129
- def spawn_application(app_root, lower_privilege = true, lowest_user = "nobody", environment = "production")
150
+ def spawn_application(app_root, options = {})
130
151
  app_root = normalize_path(app_root)
131
152
  assert_valid_app_root(app_root)
153
+ options = sanitize_spawn_options(options)
154
+ options["app_root"] = app_root
155
+
132
156
  exception_to_propagate = nil
133
157
  begin
134
- server.write("spawn_application", app_root, lower_privilege, lowest_user, environment)
158
+ server.write("spawn_application", *options.to_a.flatten)
135
159
  result = server.read
136
160
  if result.nil?
137
161
  raise IOError, "Connection closed"
138
162
  end
139
163
  if result[0] == 'exception'
140
- raise unmarshal_exception(server.read_scalar)
164
+ e = unmarshal_exception(server.read_scalar)
165
+ if e.respond_to?(:child_exception) && e.child_exception
166
+ #print_exception(self.class.to_s, e.child_exception)
167
+ end
168
+ raise e
141
169
  else
142
- pid, listen_socket_name, using_abstract_namespace = server.read
170
+ pid, listen_socket_name, socket_type = server.read
143
171
  if pid.nil?
144
172
  raise IOError, "Connection closed"
145
173
  end
146
174
  owner_pipe = server.recv_io
147
175
  return Application.new(app_root, pid, listen_socket_name,
148
- using_abstract_namespace == "true", owner_pipe)
176
+ socket_type, owner_pipe)
149
177
  end
150
178
  rescue SystemCallError, IOError, SocketError => e
151
179
  raise Error, "The framework spawner server exited unexpectedly"
@@ -191,16 +219,7 @@ protected
191
219
  # Overrided method.
192
220
  def initialize_server # :nodoc:
193
221
  $0 = "Passenger FrameworkSpawner: #{@version || @vendor}"
194
- @spawners = {}
195
- @spawners_lock = Mutex.new
196
- @spawners_cond = ConditionVariable.new
197
- @spawners_cleaner = Thread.new do
198
- begin
199
- spawners_cleaner_main_loop
200
- rescue Exception => e
201
- print_exception(self.class.to_s, e)
202
- end
203
- end
222
+ @spawners = AbstractServerCollection.new
204
223
  begin
205
224
  preload_rails
206
225
  rescue StandardError, ScriptError, NoMemoryError => e
@@ -213,13 +232,7 @@ protected
213
232
 
214
233
  # Overrided method.
215
234
  def finalize_server # :nodoc:
216
- @spawners_lock.synchronize do
217
- @spawners_cond.signal
218
- end
219
- @spawners_cleaner.join
220
- @spawners.each_value do |spawner|
221
- spawner.stop
222
- end
235
+ @spawners.cleanup
223
236
  end
224
237
 
225
238
  private
@@ -258,31 +271,36 @@ private
258
271
  Object.send(:remove_const, :RAILS_ROOT)
259
272
  end
260
273
 
261
- def handle_spawn_application(app_root, lower_privilege, lowest_user, environment)
262
- lower_privilege = lower_privilege == "true"
263
- @spawners_lock.synchronize do
264
- spawner = @spawners[app_root]
265
- if spawner.nil?
266
- begin
267
- spawner = ApplicationSpawner.new(app_root,
268
- lower_privilege, lowest_user,
269
- environment)
270
- spawner.start
271
- rescue ArgumentError, AppInitError, ApplicationSpawner::Error => e
272
- client.write('exception')
273
- client.write_scalar(marshal_exception(e))
274
- if e.child_exception.is_a?(LoadError)
275
- # A source file failed to load, maybe because of a
276
- # missing gem. If that's the case then the sysadmin
277
- # will install probably the gem. So we clear RubyGems's
278
- # cache so that it can detect new gems.
279
- Gem.clear_paths
274
+ def handle_spawn_application(*options)
275
+ options = Hash[*options]
276
+ options["lower_privilege"] = options["lower_privilege"] == "true"
277
+ options["app_spawner_timeout"] = options["app_spawner_timeout"].to_i
278
+ options["memory_limit"] = options["memory_limit"].to_i
279
+
280
+ app = nil
281
+ app_root = options["app_root"]
282
+ @spawners.synchronize do
283
+ begin
284
+ spawner = @spawners.lookup_or_add(app_root) do
285
+ spawner = ApplicationSpawner.new(app_root, options)
286
+ if options["app_spawner_timeout"] && options["app_spawner_timeout"] != -1
287
+ spawner.max_idle_time = options["app_spawner_timeout"]
280
288
  end
281
- return
289
+ spawner.start
290
+ spawner
282
291
  end
283
- @spawners[app_root] = spawner
292
+ rescue ArgumentError, AppInitError, ApplicationSpawner::Error => e
293
+ client.write('exception')
294
+ client.write_scalar(marshal_exception(e))
295
+ if e.child_exception.is_a?(LoadError)
296
+ # A source file failed to load, maybe because of a
297
+ # missing gem. If that's the case then the sysadmin
298
+ # will install probably the gem. So we clear RubyGems's
299
+ # cache so that it can detect new gems.
300
+ Gem.clear_paths
301
+ end
302
+ return
284
303
  end
285
- spawner.time = Time.now
286
304
  begin
287
305
  app = spawner.spawn_application
288
306
  rescue ApplicationSpawner::Error => e
@@ -292,53 +310,23 @@ private
292
310
  client.write_scalar(marshal_exception(e))
293
311
  return
294
312
  end
295
- client.write('success')
296
- client.write(app.pid, app.listen_socket_name, app.using_abstract_namespace?)
297
- client.send_io(app.owner_pipe)
298
- app.close
299
313
  end
314
+ client.write('success')
315
+ client.write(app.pid, app.listen_socket_name, app.listen_socket_type)
316
+ client.send_io(app.owner_pipe)
317
+ app.close
300
318
  end
301
319
 
302
320
  def handle_reload(app_root = nil)
303
- @spawners_lock.synchronize do
304
- if app_root.nil?
305
- @spawners.each_value do |spawner|
306
- spawner.stop
307
- end
308
- @spawners.clear
321
+ @spawners.synchronize do
322
+ if app_root
323
+ @spawners.delete(app_root)
309
324
  else
310
- spawner = @spawners[app_root]
311
- if spawner
312
- spawner.stop
313
- @spawners.delete(app_root)
314
- end
315
- end
316
- end
317
- end
318
-
319
- # The main loop for the spawners cleaner thread.
320
- # This thread checks the spawners list every APP_SPAWNER_CLEAN_INTERVAL seconds,
321
- # and stops application spawners that have been idle for more than
322
- # APP_SPAWNER_MAX_IDLE_TIME seconds.
323
- def spawners_cleaner_main_loop
324
- @spawners_lock.synchronize do
325
- while true
326
- if @spawners_cond.timed_wait(@spawners_lock, APP_SPAWNER_CLEAN_INTERVAL)
327
- break
328
- else
329
- current_time = Time.now
330
- @spawners.keys.each do |key|
331
- spawner = @spawners[key]
332
- if current_time - spawner.time > APP_SPAWNER_MAX_IDLE_TIME
333
- spawner.stop
334
- @spawners.delete(key)
335
- end
336
- end
337
- end
325
+ @spawners.clear
338
326
  end
339
327
  end
340
328
  end
341
329
  end
342
330
 
343
331
  end # module Railz
344
- end # module Passenger
332
+ end # module PhusionPassenger