passenger 2.1.3 → 2.2.0

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 (398) hide show
  1. data/DEVELOPERS.TXT +2 -0
  2. data/INSTALL +3 -1
  3. data/LICENSE +19 -355
  4. data/NEWS +3 -0
  5. data/README +11 -4
  6. data/Rakefile +435 -236
  7. data/bin/passenger-config +20 -14
  8. data/bin/passenger-install-apache2-module +67 -201
  9. data/bin/passenger-install-nginx-module +477 -0
  10. data/bin/passenger-make-enterprisey +17 -12
  11. data/bin/passenger-memory-stats +33 -23
  12. data/bin/passenger-spawn-server +17 -12
  13. data/bin/passenger-status +18 -13
  14. data/bin/passenger-stress-test +17 -12
  15. data/doc/{Users guide.html → Users guide Apache.html } +79 -61
  16. data/doc/{Users guide.txt → Users guide Apache.txt } +43 -939
  17. data/doc/Users guide Nginx.html +2276 -0
  18. data/doc/Users guide Nginx.txt +776 -0
  19. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +9 -4
  20. data/doc/cxxapi/ApplicationPool_8h-source.html +9 -4
  21. data/doc/cxxapi/Application_8h-source.html +26 -21
  22. data/doc/cxxapi/Bucket_8h-source.html +54 -44
  23. data/doc/cxxapi/CachedFileStat_8h-source.html +9 -4
  24. data/doc/cxxapi/Configuration_8h-source.html +357 -339
  25. data/doc/cxxapi/DirectoryMapper_8h-source.html +294 -280
  26. data/doc/cxxapi/DummySpawnManager_8h-source.html +9 -4
  27. data/doc/cxxapi/Exceptions_8h-source.html +9 -4
  28. data/doc/cxxapi/FileChecker_8h-source.html +9 -4
  29. data/doc/cxxapi/Hooks_8h-source.html +50 -40
  30. data/doc/cxxapi/Logging_8h-source.html +9 -4
  31. data/doc/cxxapi/MessageChannel_8h-source.html +20 -15
  32. data/doc/cxxapi/PoolOptions_8h-source.html +10 -5
  33. data/doc/cxxapi/SpawnManager_8h-source.html +9 -4
  34. data/doc/cxxapi/StandardApplicationPool_8h-source.html +10 -5
  35. data/doc/cxxapi/SystemTime_8h-source.html +9 -4
  36. data/doc/cxxapi/Utils_8h-source.html +242 -214
  37. data/doc/cxxapi/annotated.html +4 -28
  38. data/doc/cxxapi/classClient-members.html +4 -4
  39. data/doc/cxxapi/classClient.html +14 -11
  40. data/doc/cxxapi/classHooks-members.html +4 -5
  41. data/doc/cxxapi/classHooks.html +26 -24
  42. data/doc/cxxapi/classPassenger_1_1Application-members.html +4 -4
  43. data/doc/cxxapi/classPassenger_1_1Application.html +40 -37
  44. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +4 -4
  45. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +95 -92
  46. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +4 -4
  47. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +26 -23
  48. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.map +1 -1
  49. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.md5 +1 -1
  50. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
  51. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +17 -17
  52. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +139 -136
  53. data/doc/cxxapi/classPassenger_1_1BufferedUpload-members.html +4 -4
  54. data/doc/cxxapi/classPassenger_1_1BufferedUpload.html +13 -10
  55. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +4 -4
  56. data/doc/cxxapi/classPassenger_1_1BusyException.html +11 -8
  57. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +4 -4
  58. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +11 -8
  59. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +4 -5
  60. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +45 -43
  61. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +4 -4
  62. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +13 -10
  63. data/doc/cxxapi/classPassenger_1_1FileChecker-members.html +4 -4
  64. data/doc/cxxapi/classPassenger_1_1FileChecker.html +22 -19
  65. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +4 -4
  66. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +12 -9
  67. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.map +1 -1
  68. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.md5 +1 -1
  69. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
  70. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +4 -4
  71. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +14 -11
  72. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.map +1 -1
  73. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.md5 +1 -1
  74. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
  75. data/doc/cxxapi/classPassenger_1_1IOException-members.html +4 -4
  76. data/doc/cxxapi/classPassenger_1_1IOException.html +12 -9
  77. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.map +1 -1
  78. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.md5 +1 -1
  79. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
  80. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +4 -4
  81. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +228 -225
  82. data/doc/cxxapi/classPassenger_1_1RuntimeException-members.html +4 -4
  83. data/doc/cxxapi/classPassenger_1_1RuntimeException.html +11 -8
  84. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +4 -4
  85. data/doc/cxxapi/classPassenger_1_1SpawnException.html +14 -11
  86. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +4 -4
  87. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +50 -47
  88. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +4 -4
  89. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +73 -70
  90. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.map +1 -1
  91. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.md5 +1 -1
  92. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
  93. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +4 -4
  94. data/doc/cxxapi/classPassenger_1_1SystemException.html +17 -14
  95. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.map +1 -1
  96. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.md5 +1 -1
  97. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
  98. data/doc/cxxapi/classPassenger_1_1SystemTime-members.html +4 -4
  99. data/doc/cxxapi/classPassenger_1_1SystemTime.html +14 -11
  100. data/doc/cxxapi/classes.html +35 -0
  101. data/doc/cxxapi/definitions_8h-source.html +9 -4
  102. data/doc/cxxapi/doxygen.css +311 -303
  103. data/doc/cxxapi/files.html +9 -18
  104. data/doc/cxxapi/functions.html +5 -224
  105. data/doc/cxxapi/functions_func.html +5 -185
  106. data/doc/cxxapi/functions_type.html +4 -4
  107. data/doc/cxxapi/functions_vars.html +4 -4
  108. data/doc/cxxapi/graph_legend.dot +19 -19
  109. data/doc/cxxapi/graph_legend.html +5 -5
  110. data/doc/cxxapi/graph_legend.png +0 -0
  111. data/doc/cxxapi/group__Configuration.html +11 -13
  112. data/doc/cxxapi/group__Configuration.png +0 -0
  113. data/doc/cxxapi/group__Core.html +10 -12
  114. data/doc/cxxapi/group__Core.png +0 -0
  115. data/doc/cxxapi/group__Exceptions.html +5 -7
  116. data/doc/cxxapi/group__Hooks.html +5 -7
  117. data/doc/cxxapi/group__Hooks.png +0 -0
  118. data/doc/cxxapi/group__Support.html +5 -624
  119. data/doc/cxxapi/hierarchy.html +6 -6
  120. data/doc/cxxapi/inherit__graph__0.map +1 -1
  121. data/doc/cxxapi/inherit__graph__0.md5 +1 -1
  122. data/doc/cxxapi/inherit__graph__0.png +0 -0
  123. data/doc/cxxapi/inherit__graph__1.map +1 -1
  124. data/doc/cxxapi/inherit__graph__1.md5 +1 -1
  125. data/doc/cxxapi/inherit__graph__1.png +0 -0
  126. data/doc/cxxapi/inherit__graph__10.map +1 -1
  127. data/doc/cxxapi/inherit__graph__10.md5 +1 -1
  128. data/doc/cxxapi/inherit__graph__10.png +0 -0
  129. data/doc/cxxapi/inherit__graph__11.map +1 -1
  130. data/doc/cxxapi/inherit__graph__11.md5 +1 -1
  131. data/doc/cxxapi/inherit__graph__11.png +0 -0
  132. data/doc/cxxapi/inherit__graph__12.map +1 -1
  133. data/doc/cxxapi/inherit__graph__12.md5 +1 -1
  134. data/doc/cxxapi/inherit__graph__12.png +0 -0
  135. data/doc/cxxapi/inherit__graph__13.map +1 -2
  136. data/doc/cxxapi/inherit__graph__13.md5 +1 -1
  137. data/doc/cxxapi/inherit__graph__13.png +0 -0
  138. data/doc/cxxapi/inherit__graph__14.map +2 -1
  139. data/doc/cxxapi/inherit__graph__14.md5 +1 -1
  140. data/doc/cxxapi/inherit__graph__14.png +0 -0
  141. data/doc/cxxapi/inherit__graph__15.map +1 -1
  142. data/doc/cxxapi/inherit__graph__15.md5 +1 -1
  143. data/doc/cxxapi/inherit__graph__15.png +0 -0
  144. data/doc/cxxapi/inherit__graph__16.map +1 -1
  145. data/doc/cxxapi/inherit__graph__16.md5 +1 -1
  146. data/doc/cxxapi/inherit__graph__16.png +0 -0
  147. data/doc/cxxapi/inherit__graph__17.map +1 -1
  148. data/doc/cxxapi/inherit__graph__17.md5 +1 -1
  149. data/doc/cxxapi/inherit__graph__17.png +0 -0
  150. data/doc/cxxapi/inherit__graph__18.map +1 -1
  151. data/doc/cxxapi/inherit__graph__18.md5 +1 -1
  152. data/doc/cxxapi/inherit__graph__18.png +0 -0
  153. data/doc/cxxapi/inherit__graph__19.map +1 -1
  154. data/doc/cxxapi/inherit__graph__19.md5 +1 -1
  155. data/doc/cxxapi/inherit__graph__19.png +0 -0
  156. data/doc/cxxapi/inherit__graph__2.map +1 -1
  157. data/doc/cxxapi/inherit__graph__2.md5 +1 -1
  158. data/doc/cxxapi/inherit__graph__2.png +0 -0
  159. data/doc/cxxapi/inherit__graph__20.map +2 -2
  160. data/doc/cxxapi/inherit__graph__20.md5 +1 -1
  161. data/doc/cxxapi/inherit__graph__20.png +0 -0
  162. data/doc/cxxapi/inherit__graph__21.map +1 -1
  163. data/doc/cxxapi/inherit__graph__21.md5 +1 -1
  164. data/doc/cxxapi/inherit__graph__21.png +0 -0
  165. data/doc/cxxapi/inherit__graph__3.map +1 -1
  166. data/doc/cxxapi/inherit__graph__3.md5 +1 -1
  167. data/doc/cxxapi/inherit__graph__3.png +0 -0
  168. data/doc/cxxapi/inherit__graph__4.map +1 -1
  169. data/doc/cxxapi/inherit__graph__4.md5 +1 -1
  170. data/doc/cxxapi/inherit__graph__4.png +0 -0
  171. data/doc/cxxapi/inherit__graph__5.map +1 -2
  172. data/doc/cxxapi/inherit__graph__5.md5 +1 -1
  173. data/doc/cxxapi/inherit__graph__5.png +0 -0
  174. data/doc/cxxapi/inherit__graph__6.map +2 -1
  175. data/doc/cxxapi/inherit__graph__6.md5 +1 -1
  176. data/doc/cxxapi/inherit__graph__6.png +0 -0
  177. data/doc/cxxapi/inherit__graph__7.map +1 -1
  178. data/doc/cxxapi/inherit__graph__7.md5 +1 -1
  179. data/doc/cxxapi/inherit__graph__7.png +0 -0
  180. data/doc/cxxapi/inherit__graph__8.map +1 -1
  181. data/doc/cxxapi/inherit__graph__8.md5 +1 -1
  182. data/doc/cxxapi/inherit__graph__8.png +0 -0
  183. data/doc/cxxapi/inherit__graph__9.map +1 -1
  184. data/doc/cxxapi/inherit__graph__9.md5 +1 -1
  185. data/doc/cxxapi/inherit__graph__9.png +0 -0
  186. data/doc/cxxapi/inherits.html +41 -41
  187. data/doc/cxxapi/main.html +4 -4
  188. data/doc/cxxapi/modules.html +4 -5
  189. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +4 -4
  190. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +13 -10
  191. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +5 -5
  192. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +16 -13
  193. data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +4 -4
  194. data/doc/cxxapi/structPassenger_1_1PoolOptions.html +63 -60
  195. data/doc/cxxapi/tabs.css +5 -2
  196. data/doc/cxxapi/tree.html +7 -81
  197. data/doc/rdoc/classes/ConditionVariable.html +59 -59
  198. data/doc/rdoc/classes/Exception.html +11 -11
  199. data/doc/rdoc/classes/GC.html +4 -4
  200. data/doc/rdoc/classes/IO.html +14 -14
  201. data/doc/rdoc/classes/PhusionPassenger.html +75 -20
  202. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +153 -0
  203. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +125 -130
  204. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +236 -236
  205. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +213 -213
  206. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +28 -28
  207. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +91 -75
  208. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +10 -10
  209. data/doc/rdoc/classes/PhusionPassenger/Application.html +64 -64
  210. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +34 -34
  211. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +13 -13
  212. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +30 -30
  213. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +10 -10
  214. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +136 -136
  215. data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +24 -24
  216. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +42 -42
  217. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +55 -53
  218. data/doc/rdoc/classes/PhusionPassenger/Railz.html +1 -1
  219. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +25 -30
  220. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +23 -23
  221. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +116 -117
  222. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +22 -22
  223. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +118 -124
  224. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +10 -10
  225. data/doc/rdoc/classes/PhusionPassenger/Utils.html +354 -354
  226. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +9 -9
  227. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +37 -37
  228. data/doc/rdoc/classes/PlatformInfo.html +282 -261
  229. data/doc/rdoc/classes/RakeExtensions.html +7 -7
  230. data/doc/rdoc/classes/Signal.html +26 -26
  231. data/doc/rdoc/created.rid +1 -1
  232. data/doc/rdoc/files/DEVELOPERS_TXT.html +6 -1
  233. data/doc/rdoc/files/README.html +15 -6
  234. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
  235. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +129 -0
  236. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +20 -13
  237. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +19 -13
  238. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +19 -13
  239. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +31 -1
  240. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +31 -1
  241. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +19 -13
  242. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +19 -13
  243. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +21 -12
  244. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +19 -13
  245. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +19 -13
  246. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +19 -13
  247. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +19 -13
  248. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +19 -13
  249. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +122 -0
  250. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +19 -13
  251. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +22 -12
  252. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +21 -12
  253. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +19 -13
  254. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +1 -1
  255. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +19 -13
  256. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +21 -12
  257. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +19 -13
  258. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +19 -13
  259. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +27 -21
  260. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +21 -12
  261. data/doc/rdoc/files/misc/rake/extensions_rb.html +21 -12
  262. data/doc/rdoc/fr_class_index.html +1 -0
  263. data/doc/rdoc/fr_file_index.html +2 -0
  264. data/doc/rdoc/fr_method_index.html +116 -112
  265. data/doc/users_guide_snippets/analysis_and_system_maintenance_tools.txt +144 -0
  266. data/doc/users_guide_snippets/appendix_a_about.txt +13 -0
  267. data/doc/users_guide_snippets/appendix_b_terminology.txt +63 -0
  268. data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +304 -0
  269. data/doc/users_guide_snippets/global_queueing_explained.txt +78 -0
  270. data/doc/users_guide_snippets/rackup_specifications.txt +75 -0
  271. data/doc/users_guide_snippets/rails_spawn_method.txt +48 -0
  272. data/doc/users_guide_snippets/tips.txt +173 -0
  273. data/ext/apache2/Bucket.cpp +17 -12
  274. data/ext/apache2/Bucket.h +17 -12
  275. data/ext/apache2/Configuration.cpp +17 -12
  276. data/ext/apache2/Configuration.h +27 -14
  277. data/ext/apache2/DirectoryMapper.h +21 -12
  278. data/ext/apache2/Hooks.cpp +67 -21
  279. data/ext/apache2/Hooks.h +17 -12
  280. data/ext/apache2/mod_passenger.c +17 -12
  281. data/ext/{apache2 → common}/Application.h +19 -14
  282. data/ext/{apache2 → common}/ApplicationPool.h +17 -12
  283. data/ext/{apache2 → common}/ApplicationPoolServer.h +18 -72
  284. data/ext/{apache2 → common}/ApplicationPoolServerExecutable.cpp +45 -104
  285. data/ext/common/ApplicationPoolStatusReporter.h +212 -0
  286. data/ext/{apache2 → common}/CachedFileStat.cpp +17 -12
  287. data/ext/{apache2 → common}/CachedFileStat.h +17 -12
  288. data/ext/{apache2 → common}/DummySpawnManager.h +17 -12
  289. data/ext/{apache2 → common}/Exceptions.h +17 -12
  290. data/ext/{apache2 → common}/FileChecker.h +17 -12
  291. data/ext/common/Logging.cpp +65 -0
  292. data/ext/{apache2 → common}/Logging.h +17 -12
  293. data/ext/{apache2 → common}/MessageChannel.h +17 -12
  294. data/ext/{apache2 → common}/PoolOptions.h +17 -12
  295. data/ext/{apache2 → common}/SpawnManager.h +17 -12
  296. data/ext/{apache2 → common}/StandardApplicationPool.h +17 -12
  297. data/ext/common/StaticString.h +147 -0
  298. data/ext/common/SystemTime.cpp +33 -0
  299. data/ext/{apache2 → common}/SystemTime.h +17 -12
  300. data/ext/{apache2 → common}/Utils.cpp +69 -12
  301. data/ext/{apache2 → common}/Utils.h +41 -12
  302. data/ext/nginx/Configuration.c +1091 -0
  303. data/ext/nginx/Configuration.h +71 -0
  304. data/ext/nginx/ContentHandler.c +1154 -0
  305. data/ext/nginx/ContentHandler.h +64 -0
  306. data/ext/nginx/HelperServer.cpp +857 -0
  307. data/ext/nginx/HttpStatusExtractor.h +161 -0
  308. data/ext/nginx/ScgiRequestParser.h +317 -0
  309. data/ext/nginx/StaticContentHandler.c +222 -0
  310. data/ext/nginx/StaticContentHandler.h +37 -0
  311. data/ext/nginx/config +41 -0
  312. data/ext/nginx/ngx_http_passenger_module.c +572 -0
  313. data/ext/nginx/ngx_http_passenger_module.h +72 -0
  314. data/ext/oxt/backtrace.cpp +8 -1
  315. data/ext/oxt/system_calls.cpp +40 -0
  316. data/ext/oxt/system_calls.hpp +14 -7
  317. data/ext/phusion_passenger/extconf.rb +17 -12
  318. data/ext/phusion_passenger/native_support.c +19 -12
  319. data/lib/phusion_passenger/abstract_installer.rb +196 -0
  320. data/lib/phusion_passenger/abstract_request_handler.rb +19 -24
  321. data/lib/phusion_passenger/abstract_server.rb +17 -12
  322. data/lib/phusion_passenger/abstract_server_collection.rb +17 -12
  323. data/lib/phusion_passenger/admin_tools.rb +23 -0
  324. data/lib/phusion_passenger/admin_tools/control_process.rb +39 -13
  325. data/lib/phusion_passenger/application.rb +17 -12
  326. data/lib/phusion_passenger/console_text_template.rb +17 -12
  327. data/lib/phusion_passenger/constants.rb +22 -11
  328. data/lib/phusion_passenger/dependencies.rb +47 -12
  329. data/lib/phusion_passenger/events.rb +17 -12
  330. data/lib/phusion_passenger/exceptions.rb +17 -12
  331. data/lib/phusion_passenger/html_template.rb +17 -12
  332. data/lib/phusion_passenger/message_channel.rb +17 -12
  333. data/lib/phusion_passenger/packaging.rb +39 -0
  334. data/lib/phusion_passenger/platform_info.rb +48 -22
  335. data/lib/phusion_passenger/rack/application_spawner.rb +22 -11
  336. data/lib/phusion_passenger/rack/request_handler.rb +21 -12
  337. data/lib/phusion_passenger/railz/application_spawner.rb +23 -23
  338. data/lib/phusion_passenger/railz/framework_spawner.rb +18 -14
  339. data/lib/phusion_passenger/railz/request_handler.rb +18 -11
  340. data/lib/phusion_passenger/simple_benchmarking.rb +17 -12
  341. data/lib/phusion_passenger/spawn_manager.rb +17 -20
  342. data/lib/phusion_passenger/templates/{apache_must_be_compiled_with_compatible_mpm.txt.erb → apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb} +0 -0
  343. data/lib/phusion_passenger/templates/{apache2_config_snippets.txt.erb → apache2/config_snippets.txt.erb} +0 -0
  344. data/lib/phusion_passenger/templates/{deployment_example.txt.erb → apache2/deployment_example.txt.erb} +0 -0
  345. data/lib/phusion_passenger/templates/{no_write_permission_to_passenger_root.txt.erb → apache2/no_write_permission_to_passenger_root.txt.erb} +0 -0
  346. data/lib/phusion_passenger/templates/{possible_solutions_for_compilation_and_installation_problems.txt.erb → apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb} +0 -0
  347. data/lib/phusion_passenger/templates/{run_installer_as_root.txt.erb → apache2/run_installer_as_root.txt.erb} +0 -0
  348. data/lib/phusion_passenger/templates/{welcome.txt.erb → apache2/welcome.txt.erb} +0 -0
  349. data/lib/phusion_passenger/templates/nginx/ask_for_extra_configure_flags.txt.erb +8 -0
  350. data/lib/phusion_passenger/templates/nginx/cannot_write_to_dir.txt.erb +11 -0
  351. data/lib/phusion_passenger/templates/nginx/config_snippets.txt.erb +17 -0
  352. data/lib/phusion_passenger/templates/nginx/config_snippets_inserted.txt.erb +20 -0
  353. data/lib/phusion_passenger/templates/nginx/confirm_extra_configure_flags.txt.erb +5 -0
  354. data/lib/phusion_passenger/templates/nginx/deployment_example.txt.erb +22 -0
  355. data/lib/phusion_passenger/templates/nginx/pcre_could_not_be_downloaded.txt.erb +11 -0
  356. data/lib/phusion_passenger/templates/nginx/pcre_could_not_be_extracted.txt.erb +11 -0
  357. data/lib/phusion_passenger/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +11 -0
  358. data/lib/phusion_passenger/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +20 -0
  359. data/lib/phusion_passenger/templates/nginx/query_download_and_install.txt.erb +21 -0
  360. data/lib/phusion_passenger/templates/nginx/run_installer_as_root.txt.erb +8 -0
  361. data/lib/phusion_passenger/templates/nginx/welcome.txt.erb +15 -0
  362. data/lib/phusion_passenger/utils.rb +20 -15
  363. data/lib/phusion_passenger/wsgi/application_spawner.rb +18 -11
  364. data/lib/phusion_passenger/wsgi/request_handler.py +23 -0
  365. data/misc/copy_boost_headers.rb +23 -0
  366. data/misc/find_owner_pipe_leaks.rb +18 -11
  367. data/misc/rake/cplusplus.rb +18 -11
  368. data/misc/rake/extensions.rb +21 -14
  369. data/misc/render_error_pages.rb +18 -11
  370. data/test/ApplicationPoolServerTest.cpp +1 -3
  371. data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +1 -1
  372. data/test/CxxTestMain.cpp +19 -3
  373. data/test/HttpStatusExtractorTest.cpp +181 -0
  374. data/test/ScgiRequestParserTest.cpp +337 -0
  375. data/test/StaticStringTest.cpp +51 -0
  376. data/test/UtilsTest.cpp +32 -0
  377. data/test/config.yml.example +5 -0
  378. data/test/{integration_tests.rb → integration_tests/apache2_tests.rb} +7 -299
  379. data/test/integration_tests/hello_world_rack_spec.rb +36 -0
  380. data/test/integration_tests/hello_world_wsgi_spec.rb +41 -0
  381. data/test/integration_tests/mycook_spec.rb +192 -0
  382. data/test/integration_tests/nginx_tests.rb +98 -0
  383. data/test/ruby/rack/application_spawner_spec.rb +40 -0
  384. data/test/stub/nginx/koi-utf +109 -0
  385. data/test/stub/nginx/koi-win +103 -0
  386. data/test/stub/nginx/mime.types +70 -0
  387. data/test/stub/nginx/nginx.conf.erb +57 -0
  388. data/test/stub/nginx/win-utf +126 -0
  389. data/test/stub/rails_apps/mycook/app/controllers/uploads_controller.rb +4 -0
  390. data/test/stub/rails_apps/mycook/config/routes.rb +1 -1
  391. data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
  392. data/test/support/Support.h +40 -0
  393. data/test/support/nginx_controller.rb +98 -0
  394. data/test/support/test_helper.rb +79 -0
  395. metadata +1091 -1028
  396. data/benchmark/DummyRequestHandler.cpp +0 -101
  397. data/ext/apache2/Logging.cpp +0 -60
  398. data/ext/apache2/SystemTime.cpp +0 -28
@@ -0,0 +1,144 @@
1
+ Phusion Passenger provides a set of tools, which are useful for system analysis,
2
+ maintenance and troubleshooting.
3
+
4
+
5
+ === Inspecting memory usage ===
6
+
7
+ Process inspection tools such as `ps` and `top` are useful, but they
8
+ link:http://groups.google.com/group/phusion-passenger/msg/1fd1c233456d3180[rarely show the correct memory usage].
9
+ The real memory usage is usually lower than what `ps` and `top` report.
10
+
11
+ There are many technical reasons why this is so, but an explanation is beyond
12
+ the scope of this Users Guide. We kindly refer the interested reader to
13
+ operating systems literature about 'virtual memory' and 'copy-on-write'.
14
+
15
+ The tool `passenger-memory-stats` allows one to easily analyze Phusion Passenger's
16
+ and Apache's real memory usage. For example:
17
+
18
+ -------------------------------------------------------
19
+ [bash@localhost root]# passenger-memory-stats
20
+ ------------- Apache processes --------------.
21
+ PID PPID Threads VMSize Private Name
22
+ ---------------------------------------------.
23
+ 5947 1 9 90.6 MB 0.5 MB /usr/sbin/apache2 -k start
24
+ 5948 5947 1 18.9 MB 0.7 MB /usr/sbin/fcgi-pm -k start
25
+ 6029 5947 1 42.7 MB 0.5 MB /usr/sbin/apache2 -k start
26
+ 6030 5947 1 42.7 MB 0.5 MB /usr/sbin/apache2 -k start
27
+ 6031 5947 1 42.5 MB 0.3 MB /usr/sbin/apache2 -k start
28
+ 6033 5947 1 42.5 MB 0.4 MB /usr/sbin/apache2 -k start
29
+ 6034 5947 1 50.5 MB 0.4 MB /usr/sbin/apache2 -k start
30
+ 23482 5947 1 82.6 MB 0.4 MB /usr/sbin/apache2 -k start
31
+ ### Processes: 8
32
+ ### Total private dirty RSS: 3.50 MB
33
+
34
+ --------- Passenger processes ---------.
35
+ PID Threads VMSize Private Name
36
+ ---------------------------------------.
37
+ 6026 1 10.9 MB 4.7 MB Passenger spawn server
38
+ 23481 1 26.7 MB 3.0 MB Passenger FrameworkSpawner: 2.0.2
39
+ 23791 1 26.8 MB 2.9 MB Passenger ApplicationSpawner: /var/www/projects/app1-foobar
40
+ 23793 1 26.9 MB 17.1 MB Rails: /var/www/projects/app1-foobar
41
+ ### Processes: 4
42
+ ### Total private dirty RSS: 27.76 M
43
+ -------------------------------------------------------
44
+
45
+ The 'Private' or 'private dirty RSS' field shows the *real* memory usage of processes. Here,
46
+ we see that all the Apache worker processes only take less than 1 MB memory each.
47
+ This is a lot less than the 50 MB-ish memory usage as shown in the 'VMSize' column
48
+ (which is what a lot of people think is the real memory usage, but is actually not).
49
+
50
+ NOTE: Private dirty RSS reporting only works on Linux. Unfortunately other operating systems
51
+ don't provide facilities for determining processes' private dirty RSS. On non-Linux systems,
52
+ the Resident Set Size is reported instead.
53
+
54
+
55
+ === Inspecting Phusion Passenger's internal status ===
56
+
57
+ One can inspect Phusion Passenger's internal status with the tool `passenger-status`.
58
+ This tool must typically be run as root. For example:
59
+
60
+ --------------------------------------------------
61
+ [bash@localhost root]# passenger-status
62
+ ----------- General information -----------
63
+ max = 6
64
+ count = 1
65
+ active = 0
66
+ inactive = 1
67
+
68
+ ----------- Domains -----------
69
+ /var/www/projects/app1-foobar:
70
+ PID: 9617 Sessions: 0 Processed: 7 Uptime: 2m 23s
71
+ --------------------------------------------------
72
+
73
+ The 'general information' section shows the following information:
74
+
75
+ max:: The maximum number of application instances that Phusion Passenger will
76
+ spawn. This equals the value given for <<PassengerMaxPoolSize,PassengerMaxPoolSize>> (Apache)
77
+ or <<PassengerMaxPoolSize,passenger_max_pool_size>> (Nginx).
78
+ count:: The number of application instances that are currently alive. This value
79
+ is always less than or equal to 'max'.
80
+ active:: The number of application instances that are currently processing
81
+ requests. This value is always less than or equal to 'count'.
82
+ inactive:: The number of application instances that are currently *not* processing
83
+ requests, i.e. are idle. Idle application instances will be shutdown after a while,
84
+ as can be specified with <<PassengerPoolIdleTime,PassengerPoolIdleTime (Apache)>>/<<PassengerPoolIdleTime,passenger_pool_idle_time (Nginx)>> (unless this
85
+ value is set to 0, in which case application instances are never shut down via idle
86
+ time). The value of 'inactive' equals `count - active`.
87
+
88
+ The 'domains' section shows, for each application directory, information about running
89
+ application instances:
90
+
91
+ Sessions:: Shows how many HTTP client are currently in the queue of that application
92
+ Instance, waiting to be processed.
93
+ Processed:: Indicates how many requests the instance has served until now. *Tip:* it's
94
+ possible to limit this number with the <<PassengerMaxRequests,PassengerMaxRequests>>
95
+ configuration directive.
96
+ Uptime:: Shows for how long the application instance has been running.
97
+
98
+ Since Phusion Passenger uses fair load balancing by default, the number of sessions for the
99
+ application instances should be fairly close to each other. For example, this is fairly
100
+ normal:
101
+ --------------------------------
102
+ PID: 4281 Sessions: 2 Processed: 7 Uptime: 5m 11s
103
+ PID: 4268 Sessions: 0 Processed: 5 Uptime: 4m 52s
104
+ PID: 4265 Sessions: 1 Processed: 6 Uptime: 5m 38s
105
+ PID: 4275 Sessions: 1 Processed: 7 Uptime: 3m 14s
106
+ --------------------------------
107
+
108
+ But if you see a "spike", i.e. an application instance has an unusually high number of
109
+ sessions compared to the others, then there might be a problem:
110
+ --------------------------------
111
+ PID: 4281 Sessions: 2 Processed: 7 Uptime: 5m 11s
112
+ PID: 17468 Sessions: 8 <-+ Processed: 2 Uptime: 4m 47s
113
+ PID: 4265 Sessions: 1 | Processed: 6 Uptime: 5m 38s
114
+ PID: 4275 Sessions: 1 | Processed: 7 Uptime: 3m 14s
115
+ |
116
+ +---- "spike"
117
+ --------------------------------
118
+
119
+ Possible reasons why spikes can occur:
120
+
121
+ . Your application is busy processing a request that takes a very long time.
122
+ If this is the case, then you might want to turn
123
+ <<PassengerUseGlobalQueue,global queuing>> on.
124
+ . Your application is frozen, i.e. has stopped responding. See
125
+ <<debugging_frozen,Debugging frozen applications>> for tips.
126
+
127
+
128
+ [[debugging_frozen]]
129
+ === Debugging frozen applications ===
130
+
131
+ If one of your application instances is frozen (stopped responding), then you
132
+ can figure out where it is frozen by killing it with 'SIGABRT'. This will cause the
133
+ application to raise an exception, with a backtrace.
134
+
135
+ The exception (with full backtrace information) is normally logged into the Apache
136
+ error log. But if your application or if its web framework has its own exception logging
137
+ routines, then exceptions might be logged into the application's log files instead.
138
+ This is the case with Ruby on Rails. So if you kill a Ruby on Rails application with
139
+ 'SIGABRT', please check the application's 'production.log' first (assuming that you're
140
+ running it in a 'production' environment). If you don't see a backtrace there, check
141
+ the Apache error log.
142
+
143
+ NOTE: It is safe to kill application instances, even in live environments. Phusion Passenger
144
+ will restart killed application instances, as if nothing bad happened.
@@ -0,0 +1,13 @@
1
+ == Appendix A: About this document ==
2
+
3
+ The text of this document is licensed under the
4
+ link:http://creativecommons.org/licenses/by-sa/3.0/[Creative Commons
5
+ Attribution-Share Alike 3.0 Unported License].
6
+
7
+ image:images/by_sa.png[link="http://creativecommons.org/licenses/by-sa/3.0/"]
8
+
9
+ Phusion Passenger is brought to you by link:http://www.phusion.nl/[Phusion].
10
+
11
+ image:images/phusion_banner.png[link="http://www.phusion.nl/"]
12
+
13
+ Phusion Passenger is a trademark of Hongli Lai & Ninh Bui.
@@ -0,0 +1,63 @@
1
+ == Appendix B: Terminology ==
2
+
3
+ [[application_root]]
4
+ === Application root ===
5
+ The root directory of an application that's served by Phusion Passenger.
6
+
7
+ In case of Ruby on Rails applications, this is the directory that contains
8
+ 'Rakefile', 'app/', 'config/', 'public/', etc. In other words, the directory
9
+ pointed to by `RAILS_ROOT`. For example, take the following directory structure:
10
+
11
+ -----------------------------------------
12
+ /apps/foo/ <------ This is the Rails application's application root!
13
+ |
14
+ +- app/
15
+ | |
16
+ | +- controllers/
17
+ | |
18
+ | +- models/
19
+ | |
20
+ | +- views/
21
+ |
22
+ +- config/
23
+ | |
24
+ | +- environment.rb
25
+ | |
26
+ | +- ...
27
+ |
28
+ +- public/
29
+ | |
30
+ | +- ...
31
+ |
32
+ +- ...
33
+ -----------------------------------------
34
+
35
+ In case of Rack applications, this is the directory that contains 'config.ru'.
36
+ For example, take the following directory structure:
37
+
38
+ -----------------------------------------
39
+ /apps/bar/ <----- This is the Rack application's application root!
40
+ |
41
+ +- public/
42
+ | |
43
+ | +- ...
44
+ |
45
+ +- config.ru
46
+ |
47
+ +- ...
48
+ -----------------------------------------
49
+
50
+ In case of Python (WSGI) applications, this is the directory that contains
51
+ 'passenger_wsgi.py'. For example, take the following directory structure:
52
+
53
+ -----------------------------------------
54
+ /apps/baz/ <----- This is the WSGI application's application root!
55
+ |
56
+ +- public/
57
+ | |
58
+ | +- ...
59
+ |
60
+ +- passenger_wsgi.py
61
+ |
62
+ +- ...
63
+ -----------------------------------------
@@ -0,0 +1,304 @@
1
+ [[spawning_methods_explained]]
2
+ == Appendix C: Spawning methods explained ==
3
+
4
+ At its core, Phusion Passenger is an HTTP proxy and process manager. It spawns
5
+ Ruby on Rails/Rack/WSGI worker processes (which may also be referred to as
6
+ 'backend processes'), and forwards incoming HTTP request to one of the worker
7
+ processes.
8
+
9
+ While this may sound simple, there's not just one way to spawn worker processes.
10
+ Let's go over the different spawning methods. For simplicity's sake, let's
11
+ assume that we're only talking about Ruby on Rails applications.
12
+
13
+ === The most straightforward and traditional way: conservative spawning ===
14
+
15
+ Phusion Passenger could create a new Ruby process, which will then load the
16
+ Rails application along with the entire Rails framework. This process will then
17
+ enter an request handling main loop.
18
+
19
+ This is the most straightforward way to spawn worker processes. If you're
20
+ familiar with the Mongrel application server, then this approach is exactly
21
+ what mongrel_cluster performs: it creates N worker processes, each which loads
22
+ a full copy of the Rails application and the Rails framework in memory. The Thin
23
+ application server employs pretty much the same approach.
24
+
25
+ Note that Phusion Passenger's version of conservative spawning differs slightly
26
+ from mongrel_cluster. Mongrel_cluster creates entirely new Ruby processes. In
27
+ programmers jargon, mongrel_cluster creates new Ruby processes by forking the
28
+ current process and exec()-ing a new Ruby interpreter. Phusion Passenger on the
29
+ other hand creates processes that reuse the already loaded Ruby interpreter. In
30
+ programmers jargon, Phusion Passenger calls fork(), but not exec().
31
+
32
+ === The smart spawning method ===
33
+
34
+ NOTE: Smart spawning is only available for Ruby on Rails applications, not for
35
+ Rack applications or WSGI applications.
36
+
37
+ While conservative spawning works well, it's not as efficient as it could be
38
+ because each worker process has its own private copy of the Rails application
39
+ as well as the Rails framework. This wastes memory as well as startup time.
40
+
41
+ image:images/conservative_spawning.png[Worker processes and conservative spawning] +
42
+ 'Figure: Worker processes and conservative spawning. Each worker process has its
43
+ own private copy of the application code and Rails framework code.'
44
+
45
+ It is possible to make the different worker processes share the memory occupied
46
+ by application and Rails framework code, by utilizing so-called
47
+ copy-on-write semantics of the virtual memory system on modern operating
48
+ systems. As a side effect, the startup time is also reduced. This is technique
49
+ is exploited by Phusion Passenger's 'smart' and 'smart-lv2' spawn methods.
50
+
51
+ ==== How it works ====
52
+
53
+ When the 'smart-lv2' spawn method is being used, Phusion Passenger will first
54
+ create a so-called 'ApplicationSpawner server' process. This process loads the
55
+ entire Rails application along with the Rails framework, by loading
56
+ 'environment.rb'. Then, whenever Phusion Passenger needs a new worker process,
57
+ it will instruct the ApplicationSpawner server to do so. The ApplicationSpawner
58
+ server will create a worker new process
59
+ that reuses the already loaded Rails application/framework. Creating a worker
60
+ process through an already running ApplicationSpawner server is very fast, about
61
+ 10 times faster than loading the Rails application/framework from scratch. If
62
+ the Ruby interpreter is copy-on-write friendly (that is, if you're running
63
+ <<reducing_memory_usage,Ruby Enterprise Edition>>) then all created worker
64
+ processes will share as much common
65
+ memory as possible. That is, they will all share the same application and Rails
66
+ framework code.
67
+
68
+ image:images/smart-lv2.png[] +
69
+ 'Figure: Worker processes and the smart-lv2 spawn method. All worker processes,
70
+ as well as the ApplicationSpawner, share the same application code and Rails
71
+ framework code.'
72
+
73
+ The 'smart' spawn method goes even further, by caching the Rails framework in
74
+ another process called the 'FrameworkSpawner server'. This process only loads
75
+ the Rails framework, not the application. When a FrameworkSpawner server is
76
+ instructed to create a new worker process, it will create a new
77
+ ApplicationSpawner to which the instruction will be delegated. All those
78
+ ApplicationSpawner servers, as well as all worker processes created by those
79
+ ApplicationSpawner servers, will share the same Rails framework code.
80
+
81
+ The 'smart-lv2' method allows different worker processes that belong to the same
82
+ application to share memory. The 'smart' method allows different worker
83
+ processes - that happen to use the same Rails version - to share memory, even if
84
+ they don't belong to the same application.
85
+
86
+ Notes:
87
+
88
+ - Vendored Rails frameworks cannot be shared by different applications, even if
89
+ both vendored Rails frameworks are the same version. So for efficiency reasons
90
+ we don't recommend vendoring Rails.
91
+ - ApplicationSpawner and FrameworkSpawner servers have an idle timeout just
92
+ like worker processes. If an ApplicationSpawner/FrameworkSpawner server hasn't
93
+ been instructed to do anything for a while, it will be shutdown in order to
94
+ conserve memory. This idle timeout is configurable.
95
+
96
+ ==== Summary of benefits ====
97
+
98
+ Suppose that Phusion Passenger needs a new worker process for an application
99
+ that uses Rails 2.2.1.
100
+
101
+ - If the 'smart-lv2' spawning method is used, and an ApplicationSpawner server
102
+ for this application is already running, then worker process creation time is
103
+ about 10 times faster than conservative spawning. This worker process will also
104
+ share application and Rails framework code memory with the ApplicationSpawner
105
+ server and the worker processes that had been spawned by this ApplicationSpawner
106
+ server.
107
+ - If the 'smart' spawning method is used, and a FrameworkSpawner server for
108
+ Rails 2.2.1 is already running, but no ApplicationSpawner server for this
109
+ application is running, then worker process creation time is about 2 times
110
+ faster than conservative spawning. If there is an ApplicationSpawner server
111
+ for this application running, then worker process creation time is about 10
112
+ times faster. This worker process will also share application and Rails
113
+ framework code memory with the ApplicationSpawner and FrameworkSpawner
114
+ servers.
115
+
116
+ You could compare ApplicationSpawner and FrameworkSpawner servers with stem
117
+ cells, that have the ability to quickly change into more specific cells (worker
118
+ process).
119
+
120
+ In practice, the smart spawning methods could mean a memory saving of about 33%,
121
+ assuming that your Ruby interpreter is <<reducing_memory_usage,copy-on-write friendly>>.
122
+
123
+ Of course, smart spawning is not without gotchas. But if you understand the
124
+ gotchas you can easily reap the benefits of smart spawning.
125
+
126
+ === Smart spawning gotcha #1: unintential file descriptor sharing ===
127
+
128
+ Because worker processes are created by forking from an ApplicationSpawner
129
+ server, it will share all file descriptors that are opened by the
130
+ ApplicationSpawner server. (This is part of the semantics of the Unix
131
+ 'fork()' system call. You might want to Google it if you're not familiar with
132
+ it.) A file descriptor is a handle which can be an opened file, an opened socket
133
+ connection, a pipe, etc. If different worker processes write to such a file
134
+ descriptor at the same time, then their write calls will be interleaved, which
135
+ may potentially cause problems.
136
+
137
+ The problem commonly involves socket connections that are unintentially being
138
+ shared. You can fix it by closing and reestablishing the connection when Phusion
139
+ Passenger is creating a new worker process. Phusion Passenger provides the API
140
+ call `PhusionPassenger.on_event(:starting_worker_process)` to do so. So you
141
+ could insert the following code in your 'environment.rb':
142
+
143
+ [source, ruby]
144
+ -----------------------------------------
145
+ if defined?(PhusionPassenger)
146
+ PhusionPassenger.on_event(:starting_worker_process) do |forked|
147
+ if forked
148
+ # We're in smart spawning mode.
149
+ ... code to reestablish socket connections here ...
150
+ else
151
+ # We're in conservative spawning mode. We don't need to do anything.
152
+ end
153
+ end
154
+ end
155
+ -----------------------------------------
156
+
157
+ Note that Phusion Passenger automatically reestablishes the connection to the
158
+ database upon creating a new worker process, which is why you normally do not
159
+ encounter any database issues when using smart spawning mode.
160
+
161
+ ==== Example 1: Memcached connection sharing (harmful) ====
162
+
163
+ Suppose we have a Rails application that connects to a Memcached server in
164
+ 'environment.rb'. This causes the ApplicationSpawner to have a socket connection
165
+ (file descriptor) to the Memcached server, as shown in the following figure:
166
+
167
+ +--------------------+
168
+ | ApplicationSpawner |-----------[Memcached server]
169
+ +--------------------+
170
+
171
+ Phusion Passenger then proceeds with creating a new Rails worker process, which
172
+ is to process incoming HTTP requests. The result will look like this:
173
+
174
+ +--------------------+
175
+ | ApplicationSpawner |------+----[Memcached server]
176
+ +--------------------+ |
177
+ |
178
+ +--------------------+ |
179
+ | Worker process 1 |-----/
180
+ +--------------------+
181
+
182
+ Since a 'fork()' makes a (virtual) complete copy of a process, all its file
183
+ descriptors will be copied as well. What we see here is that ApplicationSpawner
184
+ and Worker process 1 both share the same connection to Memcached.
185
+
186
+ Now supposed that your site gets Slashdotted and Phusion Passenger needs to
187
+ spawn another worker process. It does so by forking ApplicationSpawner. The
188
+ result is now as follows:
189
+
190
+ +--------------------+
191
+ | ApplicationSpawner |------+----[Memcached server]
192
+ +--------------------+ |
193
+ |
194
+ +--------------------+ |
195
+ | Worker process 1 |-----/|
196
+ +--------------------+ |
197
+ |
198
+ +--------------------+ |
199
+ | Worker process 2 |-----/
200
+ +--------------------+
201
+
202
+ As you can see, Worker process 1 and Worker process 2 have the same Memcache
203
+ connection.
204
+
205
+ Suppose that users Joe and Jane visit your website at the same time. Joe's
206
+ request is handled by Worker process 1, and Jane's request is handled by Worker
207
+ process 2. Both worker processes want to fetch something from Memcached. Suppose
208
+ that in order to do that, both handlers need to send a "FETCH" command to Memcached.
209
+
210
+ But suppose that, after worker process 1 having only sent "FE", a context switch
211
+ occurs, and worker process 2 starts sending a "FETCH" command to Memcached as
212
+ well. If worker process 2 succeeds in sending only one bye, 'F', then Memcached
213
+ will receive a command which begins with "FEF", a command that it does not
214
+ recognize. In other words: the data from both handlers get interleaved. And thus
215
+ Memcached is forced to handle this as an error.
216
+
217
+ This problem can be solved by reestablishing the connection to Memcached after forking:
218
+
219
+ +--------------------+
220
+ | ApplicationSpawner |------+----[Memcached server]
221
+ +--------------------+ | |
222
+ | |
223
+ +--------------------+ | |
224
+ | Worker process 1 |-----/| |
225
+ +--------------------+ | | <--- created this
226
+ X | new
227
+ | connection
228
+ X <-- closed this |
229
+ +--------------------+ | old |
230
+ | Worker process 2 |-----/ connection |
231
+ +--------------------+ |
232
+ | |
233
+ +-------------------------------------+
234
+
235
+ Worker process 2 now has its own, separate communication channel with Memcached.
236
+ The code in 'environment.rb' looks like this:
237
+
238
+ [source, ruby]
239
+ -----------------------------------------
240
+ if defined?(PhusionPassenger)
241
+ PhusionPassenger.on_event(:starting_worker_process) do |forked|
242
+ if forked
243
+ # We're in smart spawning mode.
244
+ reestablish_connection_to_memcached
245
+ else
246
+ # We're in conservative spawning mode. We don't need to do anything.
247
+ end
248
+ end
249
+ end
250
+ -----------------------------------------
251
+
252
+ ==== Example 2: Log file sharing (not harmful) ====
253
+
254
+ There are also cases in which unintential file descriptor sharing is not harmful.
255
+ One such case is log file file descriptor sharing. Even if two processes write
256
+ to the log file at the same time, the worst thing that can happen is that the
257
+ data in the log file is interleaved.
258
+
259
+ To guarantee that the data written to the log file is never interleaved, you
260
+ must synchronize write access via an inter-process synchronization mechanism,
261
+ such as file locks. Reopening the log file, like you would have done in the
262
+ Memcached example, doesn't help.
263
+
264
+ === Smart spawning gotcha #2: the need to revive threads ===
265
+
266
+ Another part of the 'fork()' system call's semantics is the fact that threads
267
+ disappear after a fork call. So if you've created any threads in environment.rb,
268
+ then those threads will no longer be running in newly created worker process.
269
+ You need to revive them when a new worker process is created. Use the
270
+ `:starting_worker_process` event that Phusion Passenger provides, like this:
271
+
272
+ [source, ruby]
273
+ -----------------------------------------
274
+ if defined?(PhusionPassenger)
275
+ PhusionPassenger.on_event(:starting_worker_process) do |forked|
276
+ if forked
277
+ # We're in smart spawning mode.
278
+ ... code to revive threads here ...
279
+ else
280
+ # We're in conservative spawning mode. We don't need to do anything.
281
+ end
282
+ end
283
+ end
284
+ -----------------------------------------
285
+
286
+ === Smart spawning gotcha #3: code load order ===
287
+
288
+ This gotcha is only applicable to the 'smart' spawn method, not the 'smart-lv2'
289
+ spawn method.
290
+
291
+ If your application expects the Rails framework to be not loaded during the
292
+ beginning of 'environment.rb', then it can cause problems when an
293
+ ApplicationSpawner is created from a FrameworkSpawner, which already has the
294
+ Rails framework loaded. The most common case is when applications try to patch
295
+ Rails by dropping a modified file that has the same name as Rails's own file,
296
+ in a path that comes earlier in the Ruby search path.
297
+
298
+ For example, suppose that we have an application which has a patched version
299
+ of 'active_record/base.rb' located in 'RAILS_ROOT/lib/patches', and
300
+ 'RAILS_ROOT/lib/patches' comes first in the Ruby load path. When conservative
301
+ spawning is used, the patched version of 'base.rb' is properly loaded. When
302
+ 'smart' (not 'smart-lv2') spawning is used, the original 'base.rb' is used
303
+ because it was already loaded, so a subsequent `require "active_record/base"`
304
+ has no effect.