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,222 @@
1
+ /*
2
+ * Copyright (C) Igor Sysoev
3
+ * Copyright (C) 2009 Phusion
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions
7
+ * are met:
8
+ * 1. Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * 2. Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ *
14
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
+ * SUCH DAMAGE.
25
+ */
26
+
27
+ #include "StaticContentHandler.h"
28
+
29
+ ngx_int_t
30
+ passenger_static_content_handler(ngx_http_request_t *r, ngx_str_t *filename)
31
+ {
32
+ u_char *last, *location;
33
+ size_t len;
34
+ ngx_int_t rc;
35
+ ngx_uint_t level;
36
+ ngx_log_t *log;
37
+ ngx_buf_t *b;
38
+ ngx_chain_t out;
39
+ ngx_open_file_info_t of;
40
+ ngx_http_core_loc_conf_t *clcf;
41
+
42
+ if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {
43
+ return NGX_HTTP_NOT_ALLOWED;
44
+ }
45
+
46
+ if (r->uri.data[r->uri.len - 1] == '/') {
47
+ return NGX_DECLINED;
48
+ }
49
+
50
+ /* TODO: Win32 */
51
+ if (r->zero_in_uri) {
52
+ return NGX_DECLINED;
53
+ }
54
+
55
+ log = r->connection->log;
56
+
57
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
58
+ "http filename: \"%s\"", filename->data);
59
+
60
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
61
+
62
+ of.test_dir = 0;
63
+ of.valid = clcf->open_file_cache_valid;
64
+ of.min_uses = clcf->open_file_cache_min_uses;
65
+ of.errors = clcf->open_file_cache_errors;
66
+ of.events = clcf->open_file_cache_events;
67
+
68
+ if (ngx_open_cached_file(clcf->open_file_cache, filename, &of, r->pool)
69
+ != NGX_OK)
70
+ {
71
+ switch (of.err) {
72
+
73
+ case 0:
74
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
75
+
76
+ case NGX_ENOENT:
77
+ case NGX_ENOTDIR:
78
+ case NGX_ENAMETOOLONG:
79
+
80
+ level = NGX_LOG_ERR;
81
+ rc = NGX_HTTP_NOT_FOUND;
82
+ break;
83
+
84
+ case NGX_EACCES:
85
+
86
+ level = NGX_LOG_ERR;
87
+ rc = NGX_HTTP_FORBIDDEN;
88
+ break;
89
+
90
+ default:
91
+
92
+ level = NGX_LOG_CRIT;
93
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
94
+ break;
95
+ }
96
+
97
+ if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
98
+ ngx_log_error(level, log, of.err,
99
+ ngx_open_file_n " \"%s\" failed", filename->data);
100
+ }
101
+
102
+ return rc;
103
+ }
104
+
105
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
106
+
107
+ if (of.is_dir) {
108
+
109
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
110
+
111
+ r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t));
112
+ if (r->headers_out.location == NULL) {
113
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
114
+ }
115
+
116
+ len = r->uri.len + 1;
117
+
118
+ if (!clcf->alias && clcf->root_lengths == NULL && r->args.len == 0) {
119
+ location = filename->data + clcf->root.len;
120
+
121
+ } else {
122
+ if (r->args.len) {
123
+ len += r->args.len + 1;
124
+ }
125
+
126
+ location = ngx_palloc(r->pool, len);
127
+ if (location == NULL) {
128
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
129
+ }
130
+
131
+ last = ngx_copy(location, r->uri.data, r->uri.len);
132
+
133
+ *last = '/';
134
+
135
+ if (r->args.len) {
136
+ *++last = '?';
137
+ ngx_memcpy(++last, r->args.data, r->args.len);
138
+ }
139
+ }
140
+
141
+ /*
142
+ * we do not need to set the r->headers_out.location->hash and
143
+ * r->headers_out.location->key fields
144
+ */
145
+
146
+ r->headers_out.location->value.len = len;
147
+ r->headers_out.location->value.data = location;
148
+
149
+ return NGX_HTTP_MOVED_PERMANENTLY;
150
+ }
151
+
152
+ #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
153
+
154
+ if (!of.is_file) {
155
+ ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
156
+ "\"%s\" is not a regular file", filename->data);
157
+
158
+ return NGX_HTTP_NOT_FOUND;
159
+ }
160
+
161
+ #endif
162
+
163
+ if (r->method & NGX_HTTP_POST) {
164
+ return NGX_HTTP_NOT_ALLOWED;
165
+ }
166
+
167
+ rc = ngx_http_discard_request_body(r);
168
+
169
+ if (rc != NGX_OK) {
170
+ return rc;
171
+ }
172
+
173
+ log->action = "sending response to client";
174
+
175
+ r->headers_out.status = NGX_HTTP_OK;
176
+ r->headers_out.content_length_n = of.size;
177
+ r->headers_out.last_modified_time = of.mtime;
178
+
179
+ if (ngx_http_set_content_type(r) != NGX_OK) {
180
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
181
+ }
182
+
183
+ if (r != r->main && of.size == 0) {
184
+ return ngx_http_send_header(r);
185
+ }
186
+
187
+ r->allow_ranges = 1;
188
+
189
+ /* we need to allocate all before the header would be sent */
190
+
191
+ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
192
+ if (b == NULL) {
193
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
194
+ }
195
+
196
+ b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
197
+ if (b->file == NULL) {
198
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
199
+ }
200
+
201
+ rc = ngx_http_send_header(r);
202
+
203
+ if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
204
+ return rc;
205
+ }
206
+
207
+ b->file_pos = 0;
208
+ b->file_last = of.size;
209
+
210
+ b->in_file = b->file_last ? 1: 0;
211
+ b->last_buf = (r == r->main) ? 1: 0;
212
+ b->last_in_chain = 1;
213
+
214
+ b->file->fd = of.fd;
215
+ b->file->name = *filename;
216
+ b->file->log = log;
217
+
218
+ out.buf = b;
219
+ out.next = NULL;
220
+
221
+ return ngx_http_output_filter(r, &out);
222
+ }
@@ -0,0 +1,37 @@
1
+ /*
2
+ * Copyright (C) Igor Sysoev
3
+ * Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
4
+ * Copyright (C) 2008 Phusion
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
+ * SUCH DAMAGE.
26
+ */
27
+
28
+ #ifndef _PASSENGER_NGINX_STATIC_CONTENT_HANDLER_H_
29
+ #define _PASSENGER_NGINX_STATIC_CONTENT_HANDLER_H_
30
+
31
+ #include <ngx_core.h>
32
+ #include <ngx_http.h>
33
+
34
+ ngx_int_t passenger_static_content_handler(ngx_http_request_t *r,
35
+ ngx_str_t *filename);
36
+
37
+ #endif /* _PASSENGER_NGINX_STATIC_CONTENT_HANDLER_H_ */
data/ext/nginx/config ADDED
@@ -0,0 +1,41 @@
1
+ if ! test -f "$ngx_addon_dir/libpassenger_common.a" || \
2
+ ! test -f "$ngx_addon_dir/libboost_oxt.a"; then
3
+ echo "*** The Phusion Passenger support files are not yet compiled. Compiling them for you... ***"
4
+ echo "*** Running 'rake nginx' in $ngx_addon_dir... ***"
5
+ if ! (cd $ngx_addon_dir; rake nginx); then
6
+ exit 1
7
+ else
8
+ echo "*** Phusion Passenger support files have been successfully compiled. ***"
9
+ fi
10
+ fi
11
+
12
+ ngx_addon_name=ngx_http_passenger_module
13
+ HTTP_MODULES="$HTTP_MODULES ngx_http_passenger_module"
14
+ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
15
+ ${ngx_addon_dir}/ngx_http_passenger_module.c \
16
+ ${ngx_addon_dir}/Configuration.c \
17
+ ${ngx_addon_dir}/ContentHandler.c \
18
+ ${ngx_addon_dir}/StaticContentHandler.c"
19
+ NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
20
+ ${ngx_addon_dir}/Configuration.h \
21
+ ${ngx_addon_dir}/ContentHandler.h \
22
+ ${ngx_addon_dir}/StaticContentHandler.h \
23
+ ${ngx_addon_dir}/ngx_http_passenger_module.h"
24
+ CORE_LIBS="$CORE_LIBS \
25
+ ${ngx_addon_dir}/libpassenger_common.a \
26
+ ${ngx_addon_dir}/libboost_oxt.a \
27
+ -lstdc++ -lpthread"
28
+
29
+ nginx_version=`grep 'NGINX_VERSION ' src/core/nginx.h | awk '{ print $3 }' | sed 's/"//g'`
30
+
31
+ nginx_major_version=`echo "$nginx_version" | cut -d . -f 1`
32
+ have=PASSENGER_NGINX_MAJOR_VERSION value="$nginx_major_version"
33
+ . auto/define
34
+
35
+ nginx_minor_version=`echo "$nginx_version" | cut -d . -f 2`
36
+ have=PASSENGER_NGINX_MINOR_VERSION value="$nginx_minor_version"
37
+ . auto/define
38
+
39
+ nginx_micro_version=`echo "$nginx_version" | cut -d . -f 3`
40
+ have=PASSENGER_NGINX_MICRO_VERSION value="$nginx_micro_version"
41
+ . auto/define
@@ -0,0 +1,572 @@
1
+ /*
2
+ * Copyright (C) Igor Sysoev
3
+ * Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
4
+ * Copyright (C) 2008 Phusion
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
+ * SUCH DAMAGE.
26
+ */
27
+
28
+ #include <ngx_config.h>
29
+ #include <ngx_core.h>
30
+ #include <nginx.h>
31
+
32
+ #include <sys/types.h>
33
+ #include <sys/stat.h>
34
+ #include <sys/wait.h>
35
+ #include <unistd.h>
36
+ #include <stdio.h>
37
+ #include <stdlib.h>
38
+ #include <time.h>
39
+ #include <signal.h>
40
+ #include <string.h>
41
+ #include <errno.h>
42
+
43
+ #include "ngx_http_passenger_module.h"
44
+ #include "Configuration.h"
45
+ #include "ContentHandler.h"
46
+
47
+
48
+ #define HELPER_SERVER_MAX_SHUTDOWN_TIME 5
49
+ #define HELPER_SERVER_PASSWORD_SIZE 64
50
+
51
+
52
+ static ngx_str_t ngx_http_scgi_script_name = ngx_string("scgi_script_name");
53
+ static pid_t helper_server_pid;
54
+ static int helper_server_admin_pipe;
55
+ static u_char helper_server_password_data[HELPER_SERVER_PASSWORD_SIZE];
56
+ const char passenger_temp_dir[NGX_MAX_PATH];
57
+ ngx_str_t passenger_schema_string;
58
+ ngx_str_t passenger_helper_server_password;
59
+ const char passenger_helper_server_socket[NGX_MAX_PATH];
60
+ CachedMultiFileStat *passenger_stat_cache;
61
+
62
+
63
+ /*
64
+ HISTORIC NOTE:
65
+ We used to register passenger_content_handler as a default content handler,
66
+ instead of setting ngx_http_core_loc_conf_t->handler. However, if
67
+ ngx_http_read_client_request_body (and thus passenger_content_handler)
68
+ returns NGX_AGAIN, then Nginx will pass the not-fully-receive file upload
69
+ data to the upstream handler even though it shouldn't. Is this an Nginx
70
+ bug? In any case, setting ngx_http_core_loc_conf_t->handler fixed the
71
+ problem.
72
+
73
+ static ngx_int_t
74
+ register_content_handler(ngx_conf_t *cf)
75
+ {
76
+ ngx_http_handler_pt *h;
77
+ ngx_http_core_main_conf_t *cmcf;
78
+
79
+ cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
80
+
81
+ h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
82
+ if (h == NULL) {
83
+ return NGX_ERROR;
84
+ }
85
+ *h = passenger_content_handler;
86
+
87
+ return NGX_OK;
88
+ }
89
+ */
90
+
91
+ static void
92
+ ignore_sigpipe()
93
+ {
94
+ struct sigaction action;
95
+
96
+ action.sa_handler = SIG_IGN;
97
+ action.sa_flags = 0;
98
+ sigemptyset(&action.sa_mask);
99
+ sigaction(SIGPIPE, &action, NULL);
100
+ }
101
+
102
+ static ngx_int_t
103
+ start_helper_server(ngx_cycle_t *cycle)
104
+ {
105
+ passenger_main_conf_t *main_conf = &passenger_main_conf;
106
+ ngx_core_conf_t *ccf;
107
+ u_char helper_server_filename[NGX_MAX_PATH];
108
+ u_char log_level_string[10];
109
+ u_char max_pool_size_string[10];
110
+ u_char max_instances_per_app_string[10];
111
+ u_char pool_idle_time_string[10];
112
+ u_char user_switching_string[2];
113
+ u_char worker_uid_string[15];
114
+ u_char worker_gid_string[15];
115
+ u_char filename[NGX_MAX_PATH];
116
+ u_char *last;
117
+ int admin_pipe[2], feedback_pipe[2], e;
118
+ pid_t pid;
119
+ long i;
120
+ ssize_t ret;
121
+ char buf;
122
+ FILE *f;
123
+
124
+ ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
125
+
126
+ /* Ignore SIGPIPE now so that, if the helper server fails to start,
127
+ * nginx doesn't get killed by the default SIGPIPE handler upon
128
+ * writing the password to the helper server.
129
+ */
130
+ ignore_sigpipe();
131
+
132
+
133
+ /* Build strings that we need later. */
134
+
135
+ ngx_memzero(helper_server_filename, sizeof(helper_server_filename));
136
+ ngx_snprintf(helper_server_filename, sizeof(helper_server_filename),
137
+ "%s/ext/nginx/HelperServer",
138
+ main_conf->root_dir.data);
139
+
140
+ ngx_memzero(log_level_string, sizeof(log_level_string));
141
+ ngx_snprintf(log_level_string, sizeof(log_level_string), "%d",
142
+ (int) main_conf->log_level);
143
+
144
+ ngx_memzero(max_pool_size_string, sizeof(max_pool_size_string));
145
+ ngx_snprintf(max_pool_size_string, sizeof(max_pool_size_string), "%d",
146
+ (int) main_conf->max_pool_size);
147
+
148
+ ngx_memzero(max_instances_per_app_string, sizeof(max_instances_per_app_string));
149
+ ngx_snprintf(max_instances_per_app_string, sizeof(max_instances_per_app_string), "%d",
150
+ (int) main_conf->max_instances_per_app);
151
+
152
+ ngx_memzero(pool_idle_time_string, sizeof(pool_idle_time_string));
153
+ ngx_snprintf(pool_idle_time_string, sizeof(pool_idle_time_string), "%d",
154
+ (int) main_conf->pool_idle_time);
155
+
156
+ ngx_memzero(user_switching_string, sizeof(user_switching_string));
157
+ ngx_snprintf(user_switching_string, 1, "%d",
158
+ (int) main_conf->user_switching);
159
+
160
+ ngx_memzero(worker_uid_string, sizeof(worker_uid_string));
161
+ ngx_snprintf(worker_uid_string, sizeof(worker_uid_string), "%L",
162
+ (long long) ccf->user);
163
+
164
+ ngx_memzero(worker_gid_string, sizeof(worker_gid_string));
165
+ ngx_snprintf(worker_gid_string, sizeof(worker_gid_string), "%L",
166
+ (long long) ccf->group);
167
+
168
+ /* Generate random password for the helper server. */
169
+
170
+ f = fopen("/dev/urandom", "r");
171
+ if (f == NULL) {
172
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
173
+ "could not generate a random password for the "
174
+ "Passenger helper server: cannot open /dev/urandom");
175
+ return NGX_ERROR;
176
+ }
177
+ ngx_memzero(helper_server_password_data, HELPER_SERVER_PASSWORD_SIZE);
178
+ if (fread(helper_server_password_data, 1, HELPER_SERVER_PASSWORD_SIZE, f)
179
+ != HELPER_SERVER_PASSWORD_SIZE) {
180
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
181
+ "could not generate a random password for the "
182
+ "Passenger helper server: cannot read sufficient "
183
+ "data from /dev/urandom");
184
+ return NGX_ERROR;
185
+ }
186
+ fclose(f);
187
+ passenger_helper_server_password.data = helper_server_password_data;
188
+ passenger_helper_server_password.len = HELPER_SERVER_PASSWORD_SIZE;
189
+
190
+
191
+ /* Now spawn the helper server. */
192
+ if (pipe(admin_pipe) == -1) {
193
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
194
+ "could not start the Passenger helper server: pipe() failed");
195
+ return NGX_ERROR;
196
+ }
197
+ if (pipe(feedback_pipe) == -1) {
198
+ close(admin_pipe[0]);
199
+ close(admin_pipe[1]);
200
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
201
+ "could not start the Passenger helper server: pipe() failed");
202
+ return NGX_ERROR;
203
+ }
204
+
205
+ pid = fork();
206
+ switch (pid) {
207
+ case 0:
208
+ /* Child process. */
209
+ close(admin_pipe[1]);
210
+ close(feedback_pipe[0]);
211
+
212
+ /* Nginx redirects stderr to the error log file. Make sure that
213
+ * stdout is redirected to the error log file as well.
214
+ */
215
+ dup2(2, 1);
216
+
217
+ /* Close all file descriptors except stdin, stdout, stderr and
218
+ * the reader part of the pipe we just created.
219
+ */
220
+ if (dup2(admin_pipe[0], 3) == -1) {
221
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
222
+ "could not start the Passenger helper server: "
223
+ "dup2() failed");
224
+ }
225
+ if (dup2(feedback_pipe[1], 4) == -1) {
226
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
227
+ "could not start the Passenger helper server: "
228
+ "dup2() failed");
229
+ }
230
+ for (i = sysconf(_SC_OPEN_MAX) - 1; i > 4; i--) {
231
+ close(i);
232
+ }
233
+
234
+ /* It seems that Nginx's Perl module unsets the
235
+ * PASSENGER_INSTANCE_TEMP_DIR environment variable, so here
236
+ * we set it again.
237
+ */
238
+ setenv("PASSENGER_INSTANCE_TEMP_DIR", passenger_temp_dir, 1);
239
+
240
+ execlp((const char *) helper_server_filename,
241
+ "PassengerNginxHelperServer",
242
+ main_conf->root_dir.data,
243
+ main_conf->ruby.data,
244
+ "3", /* Admin pipe file descriptor number. */
245
+ "4", /* Feedback pipe file descriptor number. */
246
+ log_level_string,
247
+ max_pool_size_string,
248
+ max_instances_per_app_string,
249
+ pool_idle_time_string,
250
+ user_switching_string,
251
+ main_conf->default_user.data,
252
+ worker_uid_string,
253
+ worker_gid_string,
254
+ NULL);
255
+ e = errno;
256
+ fprintf(stderr, "*** Could not start the Passenger helper server (%s): "
257
+ "exec() failed: %s (%d)\n",
258
+ (const char *) helper_server_filename, strerror(e), e);
259
+ _exit(1);
260
+
261
+ case -1:
262
+ /* Error */
263
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
264
+ "could not start the Passenger helper server: "
265
+ "fork() failed");
266
+ close(admin_pipe[0]);
267
+ close(admin_pipe[1]);
268
+ close(feedback_pipe[0]);
269
+ close(feedback_pipe[1]);
270
+ return NGX_ERROR;
271
+
272
+ default:
273
+ /* Parent process. */
274
+ close(admin_pipe[0]);
275
+ close(feedback_pipe[1]);
276
+
277
+ /* Pass our auto-generated password to the helper server. */
278
+ i = 0;
279
+ do {
280
+ ret = write(admin_pipe[1], helper_server_password_data,
281
+ HELPER_SERVER_PASSWORD_SIZE - i);
282
+ if (ret == -1) {
283
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
284
+ "could not send password to the Passenger helper server: "
285
+ "write() failed");
286
+ close(admin_pipe[1]);
287
+ kill(pid, SIGTERM);
288
+ waitpid(pid, NULL, 0);
289
+ return NGX_ERROR;
290
+ } else {
291
+ i += ret;
292
+ }
293
+ } while (i < HELPER_SERVER_PASSWORD_SIZE);
294
+
295
+ /* Wait until the HelperServer has done initializing. */
296
+ read(feedback_pipe[0], &buf, 1);
297
+ close(feedback_pipe[0]);
298
+
299
+ /* Create the file passenger_temp_dir + "/control_process.pid"
300
+ * and make it writable by the worker processes. This is because
301
+ * save_master_process_pid is run after Nginx has lowered privileges.
302
+ */
303
+ last = ngx_snprintf(filename, sizeof(filename) - 1,
304
+ "%s/control_process.pid", passenger_temp_dir);
305
+ *last = (u_char) '\0';
306
+ f = fopen((const char *) filename, "w");
307
+ if (f != NULL) {
308
+ fchmod(fileno(f), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
309
+ fchown(fileno(f), ccf->user, ccf->group);
310
+ fclose(f);
311
+ } else {
312
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
313
+ "could not create %s", filename);
314
+ }
315
+
316
+ helper_server_pid = pid;
317
+ helper_server_admin_pipe = admin_pipe[1];
318
+ break;
319
+ }
320
+
321
+ return NGX_OK;
322
+ }
323
+
324
+ /**
325
+ * Save the Nginx master process's PID into a file under the Phusion Passenger
326
+ * temp directory.
327
+ *
328
+ * A bug/limitation in Nginx doesn't allow us to initialize the temp dir *after*
329
+ * Nginx has daemonized, so the temp dir's filename contains Nginx's PID before
330
+ * daemonization. Normally PhusionPassenger::AdminTools::ControlProcess (used
331
+ * by e.g. passenger-status) will think that the temp dir is stale because the
332
+ * PID in the filename doesn't exist. This PID file tells AdminTools::ControlProcess
333
+ * what the actual PID is.
334
+ */
335
+ static ngx_int_t
336
+ save_master_process_pid(ngx_cycle_t *cycle) {
337
+ u_char filename[NGX_MAX_PATH];
338
+ u_char *last;
339
+ FILE *f;
340
+
341
+ last = ngx_snprintf(filename, sizeof(filename) - 1,
342
+ "%s/control_process.pid", passenger_temp_dir);
343
+ *last = (u_char) '\0';
344
+
345
+ f = fopen((const char *) filename, "w");
346
+ if (f != NULL) {
347
+ fprintf(f, "%ld", (long) getppid());
348
+ fclose(f);
349
+ } else {
350
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
351
+ "could not create %s", filename);
352
+ }
353
+
354
+ return NGX_OK;
355
+ }
356
+
357
+ static void
358
+ shutdown_helper_server(ngx_cycle_t *cycle)
359
+ {
360
+ time_t begin_time;
361
+ int helper_server_exited;
362
+ u_char command[NGX_MAX_PATH + 10];
363
+
364
+ /* We write one byte to the admin pipe, doesn't matter what the byte is.
365
+ * The helper server will detect this as an exit command.
366
+ */
367
+ write(helper_server_admin_pipe, "x", 1);
368
+ close(helper_server_admin_pipe);
369
+
370
+ /* Wait at most HELPER_SERVER_MAX_SHUTDOWN_TIME seconds for the helper
371
+ * server to exit.
372
+ */
373
+ begin_time = time(NULL);
374
+ helper_server_exited = 0;
375
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cycle->log, 0,
376
+ "Waiting for Passenger helper server (PID %l) to exit...",
377
+ (long) helper_server_pid);
378
+ while (!helper_server_exited && time(NULL) - begin_time < HELPER_SERVER_MAX_SHUTDOWN_TIME) {
379
+ pid_t ret;
380
+
381
+ ret = waitpid(helper_server_pid, NULL, WNOHANG);
382
+ if (ret > 0 || (ret == -1 && errno == ECHILD)) {
383
+ helper_server_exited = 1;
384
+ } else {
385
+ usleep(100000);
386
+ }
387
+ }
388
+
389
+ /* Kill helper server if it did not exit in time. */
390
+ if (!helper_server_exited) {
391
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cycle->log, 0,
392
+ "Passenger helper server did not exit in time. "
393
+ "Killing it...");
394
+ kill(helper_server_pid, SIGTERM);
395
+ waitpid(helper_server_pid, NULL, 0);
396
+ }
397
+
398
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cycle->log, 0,
399
+ "Passenger helper server exited.");
400
+
401
+
402
+ /* Remove Passenger temp dir. */
403
+ ngx_memzero(command, sizeof(command));
404
+ if (ngx_snprintf(command, sizeof(command), "chmod -R u=rwx \"%s\"",
405
+ passenger_temp_dir) != NULL) {
406
+ system((const char *) command);
407
+ }
408
+
409
+ ngx_memzero(command, sizeof(command));
410
+ if (ngx_snprintf(command, sizeof(command), "rm -rf \"%s\"",
411
+ passenger_temp_dir) != NULL) {
412
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cycle->log, 0,
413
+ "Removing Passenger temp folder with command: %s",
414
+ command);
415
+ errno = 0;
416
+ if (system((const char *) command) != 0) {
417
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
418
+ "Could not remove Passenger temp folder '%s'",
419
+ passenger_temp_dir);
420
+ }
421
+ }
422
+ }
423
+
424
+ static ngx_int_t
425
+ ngx_http_scgi_script_name_variable(ngx_http_request_t *r,
426
+ ngx_http_variable_value_t *v, uintptr_t data)
427
+ {
428
+ u_char *p;
429
+ passenger_loc_conf_t *slcf;
430
+
431
+ if (r->uri.len) {
432
+ v->valid = 1;
433
+ v->no_cacheable = 0;
434
+ v->not_found = 0;
435
+
436
+ slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module);
437
+
438
+ if (r->uri.data[r->uri.len - 1] != '/') {
439
+ v->len = r->uri.len;
440
+ v->data = r->uri.data;
441
+ return NGX_OK;
442
+ }
443
+
444
+ v->len = r->uri.len + slcf->index.len;
445
+
446
+ v->data = ngx_palloc(r->pool, v->len);
447
+ if (v->data == NULL) {
448
+ return NGX_ERROR;
449
+ }
450
+
451
+ p = ngx_copy(v->data, r->uri.data, r->uri.len);
452
+ ngx_memcpy(p, slcf->index.data, slcf->index.len);
453
+
454
+ } else {
455
+ v->len = 0;
456
+ v->valid = 1;
457
+ v->no_cacheable = 0;
458
+ v->not_found = 0;
459
+ v->data = NULL;
460
+
461
+ return NGX_OK;
462
+ }
463
+
464
+ return NGX_OK;
465
+ }
466
+
467
+ static ngx_int_t
468
+ add_variables(ngx_conf_t *cf)
469
+ {
470
+ ngx_http_variable_t *var;
471
+
472
+ var = ngx_http_add_variable(cf, &ngx_http_scgi_script_name,
473
+ NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE);
474
+ if (var == NULL) {
475
+ return NGX_ERROR;
476
+ }
477
+
478
+ var->get_handler = ngx_http_scgi_script_name_variable;
479
+
480
+ return NGX_OK;
481
+ }
482
+
483
+ static ngx_int_t
484
+ pre_config_init(ngx_conf_t *cf)
485
+ {
486
+ ngx_int_t ret;
487
+ const char *system_temp_dir;
488
+ u_char command[NGX_MAX_PATH + 30];
489
+
490
+ ngx_memzero(&passenger_main_conf, sizeof(passenger_main_conf_t));
491
+
492
+ passenger_schema_string.data = (u_char *) "passenger://";
493
+ passenger_schema_string.len = sizeof("passenger://") - 1;
494
+
495
+ passenger_stat_cache = cached_multi_file_stat_new(1024);
496
+
497
+ ret = add_variables(cf);
498
+ if (ret != NGX_OK) {
499
+ return ret;
500
+ }
501
+
502
+ /* Setup Passenger temp folder. */
503
+
504
+ system_temp_dir = getenv("TMPDIR");
505
+ if (!system_temp_dir || !*system_temp_dir) {
506
+ system_temp_dir = "/tmp";
507
+ }
508
+
509
+ ngx_memzero(&passenger_temp_dir, sizeof(passenger_temp_dir));
510
+ if (ngx_snprintf((u_char *) passenger_temp_dir, sizeof(passenger_temp_dir),
511
+ "%s/passenger.%d", system_temp_dir, getpid()) == NULL) {
512
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
513
+ "could not create Passenger temp dir string");
514
+ return NGX_ERROR;
515
+ }
516
+ setenv("PASSENGER_INSTANCE_TEMP_DIR", passenger_temp_dir, 1);
517
+
518
+ /* Temporarily create this temp directory. It must exist before the configuration is loaded,
519
+ * because during Configuration loading Nginx's upstream module will attempt to create
520
+ * the directory passenger_temp_dir + "/webserver_private".
521
+ *
522
+ * passenger_temp_dir will be removed and recreated by the HelperServer, with the right
523
+ * permissions. So right now we don't have to pay any attention to the permissions.
524
+ */
525
+ ngx_memzero(command, sizeof(command));
526
+ ngx_snprintf(command, sizeof(command), "mkdir -p \"%s\"", passenger_temp_dir);
527
+ system((const char *) command);
528
+
529
+ /* Build helper server socket filename string. */
530
+
531
+ if (ngx_snprintf((u_char *) passenger_helper_server_socket, NGX_MAX_PATH,
532
+ "unix:%s/master/helper_server.sock",
533
+ passenger_temp_dir) == NULL) {
534
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
535
+ "could not create Passenger helper server "
536
+ "socket filename string");
537
+ return NGX_ERROR;
538
+ }
539
+
540
+ return NGX_OK;
541
+ }
542
+
543
+
544
+ static ngx_http_module_t passenger_module_ctx = {
545
+ pre_config_init, /* preconfiguration */
546
+ /* register_content_handler */ NULL, /* postconfiguration */
547
+
548
+ passenger_create_main_conf, /* create main configuration */
549
+ passenger_init_main_conf, /* init main configuration */
550
+
551
+ NULL, /* create server configuration */
552
+ NULL, /* merge server configuration */
553
+
554
+ passenger_create_loc_conf, /* create location configuration */
555
+ passenger_merge_loc_conf /* merge location configuration */
556
+ };
557
+
558
+
559
+ ngx_module_t ngx_http_passenger_module = {
560
+ NGX_MODULE_V1,
561
+ &passenger_module_ctx, /* module context */
562
+ (ngx_command_t *) passenger_commands, /* module directives */
563
+ NGX_HTTP_MODULE, /* module type */
564
+ NULL, /* init master */
565
+ start_helper_server, /* init module */
566
+ save_master_process_pid, /* init process */
567
+ NULL, /* init thread */
568
+ NULL, /* exit thread */
569
+ NULL, /* exit process */
570
+ shutdown_helper_server, /* exit master */
571
+ NGX_MODULE_V1_PADDING
572
+ };