passenger 2.0.6 → 2.1.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (497) hide show
  1. data/DEVELOPERS.TXT +10 -4
  2. data/LICENSE +1 -1
  3. data/NEWS +0 -0
  4. data/Rakefile +183 -117
  5. data/benchmark/dispatcher.rb +5 -9
  6. data/bin/passenger-install-apache2-module +52 -18
  7. data/bin/passenger-memory-stats +67 -13
  8. data/bin/passenger-spawn-server +8 -4
  9. data/bin/passenger-status +21 -46
  10. data/bin/passenger-stress-test +5 -5
  11. data/debian/postinst +1 -1
  12. data/doc/ApplicationPool algorithm.txt +180 -128
  13. data/doc/Architectural overview.html +1 -778
  14. data/doc/Security of user switching support.html +1 -643
  15. data/doc/Users guide Apache.html +3127 -0
  16. data/doc/Users guide Nginx.html +1458 -0
  17. data/doc/Users guide.html +1404 -467
  18. data/doc/Users guide.txt +843 -105
  19. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +751 -641
  20. data/doc/cxxapi/ApplicationPool_8h-source.html +168 -171
  21. data/doc/cxxapi/Application_8h-source.html +494 -394
  22. data/doc/cxxapi/Bucket_8h-source.html +21 -15
  23. data/doc/cxxapi/CachedFileStat_8h-source.html +191 -0
  24. data/doc/cxxapi/Configuration_8h-source.html +311 -149
  25. data/doc/cxxapi/DirectoryMapper_8h-source.html +309 -0
  26. data/doc/cxxapi/DummySpawnManager_8h-source.html +3 -4
  27. data/doc/cxxapi/Exceptions_8h-source.html +182 -165
  28. data/doc/cxxapi/FileChecker_8h-source.html +130 -0
  29. data/doc/cxxapi/Hooks_8h-source.html +2 -3
  30. data/doc/cxxapi/Logging_8h-source.html +92 -89
  31. data/doc/cxxapi/MessageChannel_8h-source.html +585 -477
  32. data/doc/cxxapi/PoolOptions_8h-source.html +305 -0
  33. data/doc/cxxapi/SpawnManager_8h-source.html +515 -540
  34. data/doc/cxxapi/StandardApplicationPool_8h-source.html +779 -679
  35. data/doc/cxxapi/SystemTime_8h-source.html +104 -0
  36. data/doc/cxxapi/Utils_8h-source.html +331 -227
  37. data/doc/cxxapi/annotated.html +6 -7
  38. data/doc/cxxapi/classClient-members.html +1 -2
  39. data/doc/cxxapi/classClient.html +1 -2
  40. data/doc/cxxapi/classHooks-members.html +5 -2
  41. data/doc/cxxapi/classHooks.html +112 -2
  42. data/doc/cxxapi/classPassenger_1_1Application-members.html +2 -3
  43. data/doc/cxxapi/classPassenger_1_1Application.html +8 -9
  44. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +4 -4
  45. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +42 -81
  46. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +1 -2
  47. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +3 -4
  48. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
  49. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +3 -2
  50. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +74 -3
  51. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +1 -2
  52. data/doc/cxxapi/classPassenger_1_1BusyException.html +2 -3
  53. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +1 -2
  54. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +2 -3
  55. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +38 -0
  56. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +256 -0
  57. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +1 -2
  58. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +2 -3
  59. data/doc/cxxapi/{classPassenger_1_1Thread-members.html → classPassenger_1_1FileChecker-members.html} +4 -5
  60. data/doc/cxxapi/classPassenger_1_1FileChecker.html +121 -0
  61. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +1 -2
  62. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +2 -3
  63. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
  64. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +2 -3
  65. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +2 -3
  66. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
  67. data/doc/cxxapi/classPassenger_1_1IOException-members.html +1 -2
  68. data/doc/cxxapi/classPassenger_1_1IOException.html +2 -3
  69. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
  70. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +5 -2
  71. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +155 -5
  72. data/doc/cxxapi/{classboost_1_1this__thread_1_1enable__syscall__interruption-members.html → classPassenger_1_1RuntimeException-members.html} +2 -3
  73. data/doc/cxxapi/{classboost_1_1this__thread_1_1enable__syscall__interruption.html → classPassenger_1_1RuntimeException.html} +10 -8
  74. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +1 -2
  75. data/doc/cxxapi/classPassenger_1_1SpawnException.html +2 -3
  76. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +2 -3
  77. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +15 -56
  78. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +5 -4
  79. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +20 -81
  80. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
  81. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +2 -3
  82. data/doc/cxxapi/classPassenger_1_1SystemException.html +9 -10
  83. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
  84. data/doc/cxxapi/{classboost_1_1this__thread_1_1disable__syscall__interruption-members.html → classPassenger_1_1SystemTime-members.html} +5 -3
  85. data/doc/cxxapi/classPassenger_1_1SystemTime.html +86 -0
  86. data/doc/cxxapi/classPassenger_1_1TempFile-members.html +2 -3
  87. data/doc/cxxapi/classPassenger_1_1TempFile.html +17 -9
  88. data/doc/cxxapi/definitions_8h-source.html +1 -2
  89. data/doc/cxxapi/files.html +6 -3
  90. data/doc/cxxapi/functions.html +98 -35
  91. data/doc/cxxapi/functions_func.html +60 -32
  92. data/doc/cxxapi/functions_type.html +1 -2
  93. data/doc/cxxapi/functions_vars.html +27 -2
  94. data/doc/cxxapi/graph_legend.html +1 -2
  95. data/doc/cxxapi/graph_legend.png +0 -0
  96. data/doc/cxxapi/group__Configuration.html +3 -4
  97. data/doc/cxxapi/group__Configuration.png +0 -0
  98. data/doc/cxxapi/group__Core.html +3 -4
  99. data/doc/cxxapi/group__Core.png +0 -0
  100. data/doc/cxxapi/group__Exceptions.html +4 -2
  101. data/doc/cxxapi/group__Hooks.html +1 -6
  102. data/doc/cxxapi/group__Hooks.png +0 -0
  103. data/doc/cxxapi/group__Support.html +259 -36
  104. data/doc/cxxapi/hierarchy.html +6 -7
  105. data/doc/cxxapi/inherit__graph__0.map +1 -1
  106. data/doc/cxxapi/inherit__graph__0.md5 +1 -1
  107. data/doc/cxxapi/inherit__graph__0.png +0 -0
  108. data/doc/cxxapi/inherit__graph__1.map +1 -1
  109. data/doc/cxxapi/inherit__graph__1.md5 +1 -1
  110. data/doc/cxxapi/inherit__graph__1.png +0 -0
  111. data/doc/cxxapi/inherit__graph__10.map +1 -1
  112. data/doc/cxxapi/inherit__graph__10.md5 +1 -1
  113. data/doc/cxxapi/inherit__graph__10.png +0 -0
  114. data/doc/cxxapi/inherit__graph__11.map +1 -1
  115. data/doc/cxxapi/inherit__graph__11.md5 +1 -1
  116. data/doc/cxxapi/inherit__graph__11.png +0 -0
  117. data/doc/cxxapi/inherit__graph__12.map +2 -1
  118. data/doc/cxxapi/inherit__graph__12.md5 +1 -1
  119. data/doc/cxxapi/inherit__graph__12.png +0 -0
  120. data/doc/cxxapi/inherit__graph__13.map +1 -1
  121. data/doc/cxxapi/inherit__graph__13.md5 +1 -1
  122. data/doc/cxxapi/inherit__graph__13.png +0 -0
  123. data/doc/cxxapi/inherit__graph__14.map +1 -2
  124. data/doc/cxxapi/inherit__graph__14.md5 +1 -1
  125. data/doc/cxxapi/inherit__graph__14.png +0 -0
  126. data/doc/cxxapi/inherit__graph__15.map +1 -1
  127. data/doc/cxxapi/inherit__graph__15.md5 +1 -1
  128. data/doc/cxxapi/inherit__graph__15.png +0 -0
  129. data/doc/cxxapi/inherit__graph__16.map +1 -1
  130. data/doc/cxxapi/inherit__graph__16.md5 +1 -1
  131. data/doc/cxxapi/inherit__graph__16.png +0 -0
  132. data/doc/cxxapi/inherit__graph__17.png +0 -0
  133. data/doc/cxxapi/inherit__graph__18.png +0 -0
  134. data/doc/cxxapi/inherit__graph__19.png +0 -0
  135. data/doc/cxxapi/inherit__graph__2.map +1 -1
  136. data/doc/cxxapi/inherit__graph__2.md5 +1 -1
  137. data/doc/cxxapi/inherit__graph__2.png +0 -0
  138. data/doc/cxxapi/inherit__graph__20.map +1 -1
  139. data/doc/cxxapi/inherit__graph__20.md5 +1 -1
  140. data/doc/cxxapi/inherit__graph__20.png +0 -0
  141. data/doc/cxxapi/inherit__graph__21.map +1 -1
  142. data/doc/cxxapi/inherit__graph__21.md5 +1 -1
  143. data/doc/cxxapi/inherit__graph__21.png +0 -0
  144. data/doc/cxxapi/inherit__graph__3.map +1 -1
  145. data/doc/cxxapi/inherit__graph__3.md5 +1 -1
  146. data/doc/cxxapi/inherit__graph__3.png +0 -0
  147. data/doc/cxxapi/inherit__graph__4.map +1 -1
  148. data/doc/cxxapi/inherit__graph__4.md5 +1 -1
  149. data/doc/cxxapi/inherit__graph__4.png +0 -0
  150. data/doc/cxxapi/inherit__graph__5.map +2 -1
  151. data/doc/cxxapi/inherit__graph__5.md5 +1 -1
  152. data/doc/cxxapi/inherit__graph__5.png +0 -0
  153. data/doc/cxxapi/inherit__graph__6.map +1 -1
  154. data/doc/cxxapi/inherit__graph__6.md5 +1 -1
  155. data/doc/cxxapi/inherit__graph__6.png +0 -0
  156. data/doc/cxxapi/inherit__graph__7.map +1 -1
  157. data/doc/cxxapi/inherit__graph__7.md5 +1 -1
  158. data/doc/cxxapi/inherit__graph__7.png +0 -0
  159. data/doc/cxxapi/inherit__graph__8.map +1 -1
  160. data/doc/cxxapi/inherit__graph__8.md5 +1 -1
  161. data/doc/cxxapi/inherit__graph__8.png +0 -0
  162. data/doc/cxxapi/inherit__graph__9.map +1 -2
  163. data/doc/cxxapi/inherit__graph__9.md5 +1 -1
  164. data/doc/cxxapi/inherit__graph__9.png +0 -0
  165. data/doc/cxxapi/inherits.html +30 -31
  166. data/doc/cxxapi/main.html +1 -2
  167. data/doc/cxxapi/modules.html +1 -2
  168. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +1 -2
  169. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +2 -3
  170. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +1 -2
  171. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +2 -3
  172. data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +49 -0
  173. data/doc/cxxapi/structPassenger_1_1PoolOptions.html +404 -0
  174. data/doc/cxxapi/tree.html +18 -20
  175. data/doc/images/conservative_spawning.png +0 -0
  176. data/doc/images/conservative_spawning.svg +248 -0
  177. data/doc/images/smart-lv2.png +0 -0
  178. data/doc/images/smart-lv2.svg +320 -0
  179. data/doc/rdoc/classes/ConditionVariable.html +68 -34
  180. data/doc/rdoc/classes/Exception.html +16 -16
  181. data/doc/rdoc/classes/GC.html +9 -9
  182. data/doc/rdoc/classes/IO.html +36 -17
  183. data/doc/rdoc/classes/PhusionPassenger.html +183 -0
  184. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +511 -0
  185. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer.html +285 -242
  186. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerAlreadyStarted.html +3 -3
  187. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerError.html +3 -3
  188. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerNotStarted.html +3 -3
  189. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/UnknownMessage.html +3 -3
  190. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +598 -0
  191. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +140 -0
  192. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +247 -0
  193. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +138 -0
  194. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AppInitError.html +36 -19
  195. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/Application.html +81 -96
  196. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/ConsoleTextTemplate.html +18 -18
  197. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/FrameworkInitError.html +20 -18
  198. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/HTMLTemplate.html +18 -18
  199. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/InitializationError.html +9 -9
  200. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +92 -0
  201. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/MessageChannel.html +93 -92
  202. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/NativeSupport.html +55 -25
  203. data/doc/rdoc/classes/PhusionPassenger/Rack.html +91 -0
  204. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +185 -0
  205. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +182 -0
  206. data/doc/rdoc/classes/PhusionPassenger/Railz.html +95 -0
  207. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +424 -0
  208. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +98 -0
  209. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +200 -0
  210. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +444 -0
  211. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +98 -0
  212. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +154 -0
  213. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +408 -0
  214. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/UnknownError.html +13 -13
  215. data/doc/rdoc/classes/PhusionPassenger/Utils.html +687 -0
  216. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/VersionNotFound.html +8 -8
  217. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +89 -0
  218. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +188 -0
  219. data/doc/rdoc/classes/PlatformInfo.html +663 -159
  220. data/doc/rdoc/classes/RakeExtensions.html +4 -4
  221. data/doc/rdoc/classes/Signal.html +134 -0
  222. data/doc/rdoc/created.rid +1 -1
  223. data/doc/rdoc/files/DEVELOPERS_TXT.html +15 -10
  224. data/doc/rdoc/files/README.html +5 -7
  225. data/doc/rdoc/files/ext/{passenger → phusion_passenger}/native_support_c.html +2 -2
  226. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/abstract_request_handler_rb.html +7 -9
  227. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +120 -0
  228. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/abstract_server_rb.html +7 -10
  229. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +99 -0
  230. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +92 -0
  231. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/application_rb.html +6 -8
  232. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/console_text_template_rb.html +5 -7
  233. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/constants_rb.html +4 -5
  234. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/dependencies_rb.html +6 -8
  235. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +116 -0
  236. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/exceptions_rb.html +5 -7
  237. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/html_template_rb.html +5 -7
  238. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/message_channel_rb.html +5 -7
  239. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/platform_info_rb.html +6 -7
  240. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +123 -0
  241. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +117 -0
  242. data/doc/rdoc/files/lib/{passenger/utils_rb.html → phusion_passenger/railz/application_spawner_rb.html} +24 -17
  243. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +126 -0
  244. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +139 -0
  245. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +118 -0
  246. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/simple_benchmarking_rb.html +5 -7
  247. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/spawn_manager_rb.html +40 -24
  248. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +169 -0
  249. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +120 -0
  250. data/doc/rdoc/files/lib/rake/extensions_rb.html +3 -4
  251. data/doc/rdoc/fr_class_index.html +37 -19
  252. data/doc/rdoc/fr_file_index.html +25 -14
  253. data/doc/rdoc/fr_method_index.html +145 -74
  254. data/ext/apache2/Application.h +145 -44
  255. data/ext/apache2/ApplicationPool.h +27 -29
  256. data/ext/apache2/ApplicationPoolServer.h +183 -72
  257. data/ext/apache2/ApplicationPoolServerExecutable.cpp +249 -42
  258. data/ext/apache2/Bucket.cpp +61 -9
  259. data/ext/apache2/Bucket.h +15 -8
  260. data/ext/apache2/CachedFileStat.cpp +114 -0
  261. data/ext/apache2/CachedFileStat.h +169 -0
  262. data/ext/apache2/Configuration.cpp +213 -22
  263. data/ext/apache2/Configuration.h +176 -13
  264. data/ext/apache2/DirectoryMapper.h +287 -0
  265. data/ext/apache2/Exceptions.h +30 -12
  266. data/ext/apache2/FileChecker.h +108 -0
  267. data/ext/apache2/Hooks.cpp +709 -493
  268. data/ext/apache2/LICENSE-CNRI.TXT +15 -0
  269. data/ext/apache2/Logging.h +26 -22
  270. data/ext/apache2/MessageChannel.h +124 -15
  271. data/ext/apache2/PoolOptions.h +283 -0
  272. data/ext/apache2/SpawnManager.h +75 -99
  273. data/ext/apache2/StandardApplicationPool.h +296 -195
  274. data/ext/apache2/SystemTime.cpp +28 -0
  275. data/ext/apache2/SystemTime.h +82 -0
  276. data/ext/apache2/Utils.cpp +172 -18
  277. data/ext/apache2/Utils.h +124 -19
  278. data/ext/boost/cstdint.hpp +4 -2
  279. data/ext/boost/current_function.hpp +67 -0
  280. data/ext/boost/detail/sp_counted_base.hpp +4 -4
  281. data/ext/boost/thread/exceptions.hpp +2 -1
  282. data/ext/boost/thread/pthread/thread.hpp +11 -3
  283. data/ext/boost/thread/pthread/thread_data.hpp +2 -1
  284. data/ext/oxt/backtrace.cpp +172 -0
  285. data/ext/oxt/backtrace.hpp +135 -0
  286. data/ext/oxt/detail/backtrace_disabled.hpp +39 -0
  287. data/ext/oxt/detail/backtrace_enabled.hpp +155 -0
  288. data/ext/oxt/detail/spin_lock_gcc_x86.hpp +82 -0
  289. data/ext/oxt/detail/spin_lock_portable.hpp +38 -0
  290. data/ext/oxt/detail/spin_lock_pthreads.hpp +97 -0
  291. data/ext/oxt/detail/tracable_exception_disabled.hpp +46 -0
  292. data/ext/oxt/detail/tracable_exception_enabled.hpp +48 -0
  293. data/ext/oxt/macros.hpp +58 -0
  294. data/ext/oxt/spin_lock.hpp +55 -0
  295. data/ext/{apache2/System.cpp → oxt/system_calls.cpp} +87 -52
  296. data/ext/oxt/system_calls.hpp +234 -0
  297. data/ext/oxt/thread.cpp +32 -0
  298. data/ext/oxt/thread.hpp +223 -0
  299. data/ext/oxt/tracable_exception.cpp +87 -0
  300. data/ext/oxt/tracable_exception.hpp +35 -0
  301. data/{lib/passenger/constants.rb → ext/phusion_passenger/extconf.rb} +14 -9
  302. data/ext/{passenger → phusion_passenger}/native_support.c +33 -6
  303. data/lib/{passenger → phusion_passenger}/abstract_request_handler.rb +209 -93
  304. data/lib/{passenger → phusion_passenger}/abstract_server.rb +23 -8
  305. data/lib/phusion_passenger/abstract_server_collection.rb +301 -0
  306. data/lib/phusion_passenger/admin_tools.rb +25 -0
  307. data/lib/phusion_passenger/admin_tools/control_process.rb +107 -0
  308. data/lib/{passenger → phusion_passenger}/application.rb +13 -16
  309. data/lib/{passenger → phusion_passenger}/console_text_template.rb +2 -2
  310. data/{ext/passenger/extconf.rb → lib/phusion_passenger/constants.rb} +5 -5
  311. data/lib/{passenger → phusion_passenger}/dependencies.rb +38 -32
  312. data/lib/phusion_passenger/events.rb +45 -0
  313. data/lib/{passenger → phusion_passenger}/exceptions.rb +12 -5
  314. data/lib/{passenger → phusion_passenger}/html_template.rb +2 -2
  315. data/lib/{passenger → phusion_passenger}/message_channel.rb +3 -2
  316. data/lib/phusion_passenger/platform_info.rb +500 -0
  317. data/lib/{passenger → phusion_passenger}/rack/application_spawner.rb +29 -22
  318. data/lib/{passenger → phusion_passenger}/rack/request_handler.rb +14 -9
  319. data/lib/{passenger → phusion_passenger}/railz/application_spawner.rb +94 -74
  320. data/lib/{passenger → phusion_passenger}/railz/cgi_fixed.rb +2 -2
  321. data/lib/{passenger → phusion_passenger}/railz/framework_spawner.rb +86 -98
  322. data/lib/{passenger → phusion_passenger}/railz/request_handler.rb +6 -6
  323. data/lib/{passenger → phusion_passenger}/simple_benchmarking.rb +0 -0
  324. data/lib/{passenger → phusion_passenger}/spawn_manager.rb +136 -128
  325. data/lib/{passenger → phusion_passenger}/templates/apache2_config_snippets.txt.erb +0 -0
  326. data/lib/{passenger → phusion_passenger}/templates/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
  327. data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +38 -0
  328. data/lib/{passenger → phusion_passenger}/templates/app_init_error.html.erb +0 -0
  329. data/lib/{passenger → phusion_passenger}/templates/database_error.html.erb +0 -0
  330. data/lib/{passenger → phusion_passenger}/templates/deployment_example.txt.erb +1 -1
  331. data/lib/{passenger → phusion_passenger}/templates/error_layout.css +0 -0
  332. data/lib/{passenger → phusion_passenger}/templates/error_layout.html.erb +0 -0
  333. data/lib/{passenger → phusion_passenger}/templates/framework_init_error.html.erb +0 -0
  334. data/lib/{passenger → phusion_passenger}/templates/general_error.html.erb +0 -0
  335. data/lib/{passenger → phusion_passenger}/templates/invalid_app_root.html.erb +1 -1
  336. data/lib/{passenger → phusion_passenger}/templates/load_error.html.erb +0 -0
  337. data/lib/{passenger → phusion_passenger}/templates/no_write_permission_to_passenger_root.txt.erb +0 -0
  338. data/lib/{passenger → phusion_passenger}/templates/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
  339. data/lib/{passenger → phusion_passenger}/templates/run_installer_as_root.txt.erb +0 -0
  340. data/lib/{passenger → phusion_passenger}/templates/version_not_found.html.erb +0 -0
  341. data/lib/{passenger → phusion_passenger}/templates/welcome.txt.erb +0 -0
  342. data/lib/{passenger → phusion_passenger}/utils.rb +210 -44
  343. data/lib/{passenger → phusion_passenger}/wsgi/application_spawner.rb +18 -15
  344. data/lib/{passenger → phusion_passenger}/wsgi/request_handler.py +7 -1
  345. data/man/passenger-memory-stats.8 +1 -1
  346. data/misc/render_error_pages.rb +1 -1
  347. data/test/ApplicationPoolServerTest.cpp +0 -28
  348. data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +4 -0
  349. data/test/ApplicationPoolTest.cpp +307 -69
  350. data/test/CachedFileStatTest.cpp +262 -0
  351. data/test/FileCheckerTest.cpp +79 -0
  352. data/test/MessageChannelTest.cpp +3 -3
  353. data/test/PoolOptionsTest.cpp +37 -0
  354. data/test/SpawnManagerTest.cpp +4 -4
  355. data/test/StandardApplicationPoolTest.cpp +4 -0
  356. data/test/SystemTimeTest.cpp +37 -0
  357. data/test/UtilsTest.cpp +137 -0
  358. data/test/integration_tests.rb +270 -23
  359. data/test/oxt/backtrace_test.cpp +128 -0
  360. data/test/oxt/oxt_test_main.cpp +25 -0
  361. data/test/oxt/syscall_interruption_test.cpp +50 -0
  362. data/test/ruby/abstract_request_handler_spec.rb +83 -0
  363. data/test/ruby/abstract_server_collection_spec.rb +246 -0
  364. data/test/ruby/application_spec.rb +3 -3
  365. data/test/ruby/message_channel_spec.rb +2 -2
  366. data/test/ruby/rack/application_spawner_spec.rb +3 -5
  367. data/test/ruby/rails/application_spawner_spec.rb +54 -15
  368. data/test/ruby/rails/framework_spawner_spec.rb +6 -8
  369. data/test/ruby/rails/minimal_spawner_spec.rb +29 -0
  370. data/test/ruby/rails/spawner_error_handling_spec.rb +1 -1
  371. data/test/ruby/rails/spawner_privilege_lowering_spec.rb +3 -3
  372. data/test/ruby/spawn_manager_spec.rb +23 -12
  373. data/test/ruby/utils_spec.rb +36 -2
  374. data/test/ruby/wsgi/application_spawner_spec.rb +47 -0
  375. data/test/stub/apache2/httpd.conf.erb +3 -5
  376. data/test/stub/message_channel.rb +2 -2
  377. data/test/stub/message_channel_2.rb +2 -2
  378. data/test/stub/message_channel_3.rb +3 -3
  379. data/test/stub/minimal-railsapp/README +0 -0
  380. data/test/stub/minimal-railsapp/config/application.rb +0 -0
  381. data/test/stub/minimal-railsapp/config/environment.rb +0 -0
  382. data/test/stub/minimal-railsapp/vendor/rails/actionmailer/lib/action_mailer.rb +0 -0
  383. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_controller.rb +0 -0
  384. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_pack.rb +0 -0
  385. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_view.rb +0 -0
  386. data/test/stub/minimal-railsapp/vendor/rails/activerecord/lib/active_record.rb +0 -0
  387. data/test/stub/minimal-railsapp/vendor/rails/activeresource/lib/active_resource.rb +0 -0
  388. data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support.rb +0 -0
  389. data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support/whiny_nil.rb +0 -0
  390. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/dispatcher.rb +0 -0
  391. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/initializer.rb +0 -0
  392. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/ruby_version_check.rb +0 -0
  393. data/test/stub/rails_apps/foobar/app/controllers/foo_controller.rb +8 -0
  394. data/test/stub/rails_apps/foobar/config/environments/development.rb +1 -2
  395. data/test/stub/rails_apps/mycook/app/controllers/welcome_controller.rb +21 -1
  396. data/test/stub/rails_apps/mycook/sites/some.site/public/uploads.html +26 -0
  397. data/test/stub/rails_apps/mycook/sites/some.site/public/welcome/cached.html +26 -0
  398. data/test/stub/railsapp/app/controllers/application.rb +0 -0
  399. data/test/stub/railsapp/app/controllers/bar_controller_1.rb +0 -0
  400. data/test/stub/railsapp/app/controllers/bar_controller_2.rb +1 -1
  401. data/test/stub/railsapp/app/controllers/foo_controller.rb +4 -0
  402. data/test/stub/railsapp/app/helpers/application_helper.rb +0 -0
  403. data/test/stub/railsapp/config/boot.rb +0 -0
  404. data/test/stub/railsapp/config/database.yml +0 -0
  405. data/test/stub/railsapp/config/environment.rb +0 -0
  406. data/test/stub/railsapp/config/environments/development.rb +0 -0
  407. data/test/stub/railsapp/config/environments/production.rb +0 -0
  408. data/test/stub/railsapp/config/initializers/inflections.rb +0 -0
  409. data/test/stub/railsapp/config/initializers/mime_types.rb +0 -0
  410. data/test/stub/railsapp/config/routes.rb +0 -0
  411. data/test/stub/railsapp/public/useless.txt +0 -0
  412. data/test/stub/spawn_server.rb +3 -4
  413. data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
  414. data/test/support/apache2_controller.rb +57 -7
  415. data/test/support/tut.h +15 -0
  416. data/vendor/README +12 -0
  417. data/vendor/README_FOR_PACKAGERS +1 -0
  418. data/vendor/rack-0.9.1/AUTHORS +8 -0
  419. data/vendor/rack-0.9.1/COPYING +18 -0
  420. data/vendor/rack-0.9.1/ChangeLog +1423 -0
  421. data/vendor/rack-0.9.1/KNOWN-ISSUES +18 -0
  422. data/vendor/rack-0.9.1/README +306 -0
  423. data/vendor/rack-0.9.1/Rakefile +188 -0
  424. data/vendor/rack-0.9.1/SPEC +129 -0
  425. data/vendor/rack-0.9.1/lib/rack.rb +86 -0
  426. data/vendor/rack-0.9.1/lib/rack/adapter/camping.rb +22 -0
  427. data/vendor/rack-0.9.1/lib/rack/auth/abstract/handler.rb +28 -0
  428. data/vendor/rack-0.9.1/lib/rack/auth/abstract/request.rb +37 -0
  429. data/vendor/rack-0.9.1/lib/rack/auth/basic.rb +58 -0
  430. data/vendor/rack-0.9.1/lib/rack/auth/digest/md5.rb +124 -0
  431. data/vendor/rack-0.9.1/lib/rack/auth/digest/nonce.rb +51 -0
  432. data/vendor/rack-0.9.1/lib/rack/auth/digest/params.rb +55 -0
  433. data/vendor/rack-0.9.1/lib/rack/auth/digest/request.rb +40 -0
  434. data/vendor/rack-0.9.1/lib/rack/auth/openid.rb +438 -0
  435. data/vendor/rack-0.9.1/lib/rack/builder.rb +67 -0
  436. data/vendor/rack-0.9.1/lib/rack/cascade.rb +36 -0
  437. data/vendor/rack-0.9.1/lib/rack/commonlogger.rb +61 -0
  438. data/vendor/rack-0.9.1/lib/rack/conditionalget.rb +43 -0
  439. data/vendor/rack-0.9.1/lib/rack/content_length.rb +25 -0
  440. data/vendor/rack-0.9.1/lib/rack/deflater.rb +87 -0
  441. data/vendor/rack-0.9.1/lib/rack/directory.rb +150 -0
  442. data/vendor/rack-0.9.1/lib/rack/file.rb +85 -0
  443. data/vendor/rack-0.9.1/lib/rack/handler.rb +48 -0
  444. data/vendor/rack-0.9.1/lib/rack/handler/cgi.rb +57 -0
  445. data/vendor/rack-0.9.1/lib/rack/handler/evented_mongrel.rb +8 -0
  446. data/vendor/rack-0.9.1/lib/rack/handler/fastcgi.rb +86 -0
  447. data/vendor/rack-0.9.1/lib/rack/handler/lsws.rb +52 -0
  448. data/vendor/rack-0.9.1/lib/rack/handler/mongrel.rb +82 -0
  449. data/vendor/rack-0.9.1/lib/rack/handler/scgi.rb +57 -0
  450. data/vendor/rack-0.9.1/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  451. data/vendor/rack-0.9.1/lib/rack/handler/thin.rb +15 -0
  452. data/vendor/rack-0.9.1/lib/rack/handler/webrick.rb +61 -0
  453. data/vendor/rack-0.9.1/lib/rack/head.rb +19 -0
  454. data/vendor/rack-0.9.1/lib/rack/lint.rb +465 -0
  455. data/vendor/rack-0.9.1/lib/rack/lobster.rb +65 -0
  456. data/vendor/rack-0.9.1/lib/rack/methodoverride.rb +27 -0
  457. data/vendor/rack-0.9.1/lib/rack/mime.rb +204 -0
  458. data/vendor/rack-0.9.1/lib/rack/mock.rb +160 -0
  459. data/vendor/rack-0.9.1/lib/rack/recursive.rb +57 -0
  460. data/vendor/rack-0.9.1/lib/rack/reloader.rb +64 -0
  461. data/vendor/rack-0.9.1/lib/rack/request.rb +218 -0
  462. data/vendor/rack-0.9.1/lib/rack/response.rb +171 -0
  463. data/vendor/rack-0.9.1/lib/rack/session/abstract/id.rb +153 -0
  464. data/vendor/rack-0.9.1/lib/rack/session/cookie.rb +89 -0
  465. data/vendor/rack-0.9.1/lib/rack/session/memcache.rb +97 -0
  466. data/vendor/rack-0.9.1/lib/rack/session/pool.rb +73 -0
  467. data/vendor/rack-0.9.1/lib/rack/showexceptions.rb +348 -0
  468. data/vendor/rack-0.9.1/lib/rack/showstatus.rb +106 -0
  469. data/vendor/rack-0.9.1/lib/rack/static.rb +38 -0
  470. data/vendor/rack-0.9.1/lib/rack/urlmap.rb +48 -0
  471. data/vendor/rack-0.9.1/lib/rack/utils.rb +347 -0
  472. metadata +1197 -1055
  473. data/doc/cxxapi/System_8h-source.html +0 -251
  474. data/doc/cxxapi/classDirectoryMapper-members.html +0 -38
  475. data/doc/cxxapi/classDirectoryMapper.html +0 -203
  476. data/doc/cxxapi/classPassenger_1_1Thread.html +0 -100
  477. data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption.html +0 -46
  478. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption-members.html +0 -33
  479. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption.html +0 -44
  480. data/doc/cxxapi/namespacePassenger.html +0 -208
  481. data/doc/cxxapi/namespacePassenger_1_1InterruptableCalls.html +0 -43
  482. data/doc/cxxapi/namespacemembers.html +0 -70
  483. data/doc/cxxapi/namespacemembers_func.html +0 -66
  484. data/doc/cxxapi/namespacemembers_type.html +0 -46
  485. data/doc/cxxapi/namespaces.html +0 -35
  486. data/doc/rdoc/classes/Passenger.html +0 -136
  487. data/doc/rdoc/classes/Passenger/AbstractRequestHandler.html +0 -402
  488. data/doc/rdoc/classes/Passenger/SpawnManager.html +0 -379
  489. data/doc/rdoc/classes/Passenger/Utils.html +0 -578
  490. data/ext/apache2/System.h +0 -228
  491. data/lib/passenger/platform_info.rb +0 -302
  492. data/lib/passenger/templates/app_exited_during_initialization.html.erb +0 -19
  493. data/test/stub/apache2/httpd.conf +0 -75
  494. data/test/stub/rails_apps/foobar/config/environments/test.rb +0 -22
  495. data/test/stub/rails_apps/mycook/config/environments/test.rb +0 -22
  496. data/test/stub/railsapp/config/environments/test.rb +0 -22
  497. data/test/stub/railsapp2/config/environments/test.rb +0 -22
@@ -22,11 +22,15 @@
22
22
 
23
23
  #include <boost/shared_ptr.hpp>
24
24
  #include <boost/function.hpp>
25
+ #include <oxt/system_calls.hpp>
26
+ #include <oxt/backtrace.hpp>
25
27
  #include <string>
28
+ #include <vector>
26
29
 
27
30
  #include <sys/types.h>
28
31
  #include <sys/socket.h>
29
32
  #include <sys/un.h>
33
+ #include <netdb.h>
30
34
  #include <unistd.h>
31
35
  #include <errno.h>
32
36
  #include <ctime>
@@ -35,6 +39,7 @@
35
39
  #include "MessageChannel.h"
36
40
  #include "Exceptions.h"
37
41
  #include "Logging.h"
42
+ #include "Utils.h"
38
43
 
39
44
  namespace Passenger {
40
45
 
@@ -105,6 +110,7 @@ public:
105
110
  * @throws boost::thread_interrupted
106
111
  */
107
112
  virtual void sendHeaders(const char *headers, unsigned int size) {
113
+ TRACE_POINT();
108
114
  int stream = getStream();
109
115
  if (stream == -1) {
110
116
  throw IOException("Cannot write headers to the request handler "
@@ -112,9 +118,10 @@ public:
112
118
  }
113
119
  try {
114
120
  MessageChannel(stream).writeScalar(headers, size);
115
- } catch (const SystemException &e) {
116
- throw SystemException("An error occured while writing headers "
117
- "to the request handler", e.code());
121
+ } catch (SystemException &e) {
122
+ e.setBriefMessage("An error occured while writing headers "
123
+ "to the request handler");
124
+ throw;
118
125
  }
119
126
  }
120
127
 
@@ -144,6 +151,7 @@ public:
144
151
  * @throws boost::thread_interrupted
145
152
  */
146
153
  virtual void sendBodyBlock(const char *block, unsigned int size) {
154
+ TRACE_POINT();
147
155
  int stream = getStream();
148
156
  if (stream == -1) {
149
157
  throw IOException("Cannot write request body block to the "
@@ -152,9 +160,10 @@ public:
152
160
  }
153
161
  try {
154
162
  MessageChannel(stream).writeRaw(block, size);
155
- } catch (const SystemException &e) {
156
- throw SystemException("An error occured while sending the "
157
- "request body to the request handler", e.code());
163
+ } catch (SystemException &e) {
164
+ e.setBriefMessage("An error occured while sending the "
165
+ "request body to the request handler");
166
+ throw;
158
167
  }
159
168
  }
160
169
 
@@ -167,6 +176,28 @@ public:
167
176
  */
168
177
  virtual int getStream() const = 0;
169
178
 
179
+ /**
180
+ * Set the timeout value for reading data from the I/O stream.
181
+ * If no data can be read within the timeout period, then the
182
+ * read call will fail with error EAGAIN or EWOULDBLOCK.
183
+ *
184
+ * @param msec The timeout, in milliseconds. If 0 is given,
185
+ * there will be no timeout.
186
+ * @throws SystemException Cannot set the timeout.
187
+ */
188
+ virtual void setReaderTimeout(unsigned int msec) = 0;
189
+
190
+ /**
191
+ * Set the timeout value for writing data from the I/O stream.
192
+ * If no data can be written within the timeout period, then the
193
+ * write call will fail with error EAGAIN or EWOULDBLOCK.
194
+ *
195
+ * @param msec The timeout, in milliseconds. If 0 is given,
196
+ * there will be no timeout.
197
+ * @throws SystemException Cannot set the timeout.
198
+ */
199
+ virtual void setWriterTimeout(unsigned int msec) = 0;
200
+
170
201
  /**
171
202
  * Indicate that we don't want to read data anymore from the I/O stream.
172
203
  * Calling this method after closeStream() is called will have no effect.
@@ -225,6 +256,7 @@ private:
225
256
  }
226
257
 
227
258
  virtual ~StandardSession() {
259
+ TRACE_POINT();
228
260
  closeStream();
229
261
  closeCallback();
230
262
  }
@@ -233,9 +265,18 @@ private:
233
265
  return fd;
234
266
  }
235
267
 
268
+ virtual void setReaderTimeout(unsigned int msec) {
269
+ MessageChannel(fd).setReadTimeout(msec);
270
+ }
271
+
272
+ virtual void setWriterTimeout(unsigned int msec) {
273
+ MessageChannel(fd).setWriteTimeout(msec);
274
+ }
275
+
236
276
  virtual void shutdownReader() {
277
+ TRACE_POINT();
237
278
  if (fd != -1) {
238
- int ret = InterruptableCalls::shutdown(fd, SHUT_RD);
279
+ int ret = syscalls::shutdown(fd, SHUT_RD);
239
280
  if (ret == -1) {
240
281
  throw SystemException("Cannot shutdown the writer stream",
241
282
  errno);
@@ -244,8 +285,9 @@ private:
244
285
  }
245
286
 
246
287
  virtual void shutdownWriter() {
288
+ TRACE_POINT();
247
289
  if (fd != -1) {
248
- int ret = InterruptableCalls::shutdown(fd, SHUT_WR);
290
+ int ret = syscalls::shutdown(fd, SHUT_WR);
249
291
  if (ret == -1) {
250
292
  throw SystemException("Cannot shutdown the writer stream",
251
293
  errno);
@@ -254,8 +296,9 @@ private:
254
296
  }
255
297
 
256
298
  virtual void closeStream() {
299
+ TRACE_POINT();
257
300
  if (fd != -1) {
258
- int ret = InterruptableCalls::close(fd);
301
+ int ret = syscalls::close(fd);
259
302
  if (ret == -1) {
260
303
  throw SystemException("Cannot close the session stream",
261
304
  errno);
@@ -276,8 +319,88 @@ private:
276
319
  string appRoot;
277
320
  pid_t pid;
278
321
  string listenSocketName;
279
- bool usingAbstractNamespace;
322
+ string listenSocketType;
280
323
  int ownerPipe;
324
+
325
+ SessionPtr connectToUnixServer(const function<void()> &closeCallback) const {
326
+ TRACE_POINT();
327
+ int fd, ret;
328
+
329
+ do {
330
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
331
+ } while (fd == -1 && errno == EINTR);
332
+ if (fd == -1) {
333
+ throw SystemException("Cannot create a new unconnected Unix socket", errno);
334
+ }
335
+
336
+ struct sockaddr_un addr;
337
+ addr.sun_family = AF_UNIX;
338
+ strncpy(addr.sun_path, listenSocketName.c_str(), sizeof(addr.sun_path));
339
+ addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
340
+ do {
341
+ ret = ::connect(fd, (const sockaddr *) &addr, sizeof(addr));
342
+ } while (ret == -1 && errno == EINTR);
343
+ if (ret == -1) {
344
+ int e = errno;
345
+ string message("Cannot connect to Unix socket '");
346
+ message.append(listenSocketName);
347
+ message.append("'");
348
+ do {
349
+ ret = close(fd);
350
+ } while (ret == -1 && errno == EINTR);
351
+ throw SystemException(message, e);
352
+ }
353
+
354
+ return ptr(new StandardSession(pid, closeCallback, fd));
355
+ }
356
+
357
+ SessionPtr connectToTcpServer(const function<void()> &closeCallback) const {
358
+ TRACE_POINT();
359
+ int fd, ret;
360
+ vector<string> args;
361
+
362
+ split(listenSocketName, ':', args);
363
+ if (args.size() != 2 || atoi(args[1]) == 0) {
364
+ throw IOException("Invalid TCP/IP address '" + listenSocketName + "'");
365
+ }
366
+
367
+ struct addrinfo hints, *res;
368
+
369
+ memset(&hints, 0, sizeof(hints));
370
+ hints.ai_family = PF_INET;
371
+ hints.ai_socktype = SOCK_STREAM;
372
+ ret = getaddrinfo(args[0].c_str(), args[1].c_str(), &hints, &res);
373
+ if (ret != 0) {
374
+ int e = errno;
375
+ throw IOException("Cannot resolve address '" + listenSocketName +
376
+ "': " + gai_strerror(e));
377
+ }
378
+
379
+ do {
380
+ fd = socket(PF_INET, SOCK_STREAM, 0);
381
+ } while (fd == -1 && errno == EINTR);
382
+ if (fd == -1) {
383
+ freeaddrinfo(res);
384
+ throw SystemException("Cannot create a new unconnected TCP socket", errno);
385
+ }
386
+
387
+ do {
388
+ ret = ::connect(fd, res->ai_addr, res->ai_addrlen);
389
+ } while (ret == -1 && errno == EINTR);
390
+ freeaddrinfo(res);
391
+ if (ret == -1) {
392
+ int e = errno;
393
+ string message("Cannot connect to TCP server '");
394
+ message.append(listenSocketName);
395
+ message.append("'");
396
+ do {
397
+ ret = close(fd);
398
+ } while (ret == -1 && errno == EINTR);
399
+ throw SystemException(message, e);
400
+ }
401
+
402
+ return ptr(new StandardSession(pid, closeCallback, fd));
403
+ }
281
404
 
282
405
  public:
283
406
  /**
@@ -288,23 +411,23 @@ public:
288
411
  * This must be a valid directory, but the path does not have to be absolute.
289
412
  * @param pid The process ID of this application instance.
290
413
  * @param listenSocketName The name of the listener socket of this application instance.
291
- * @param usingAbstractNamespace Whether <tt>listenSocketName</tt> refers to a Unix
292
- * socket on the abstract namespace. Note that listenSocketName must not
293
- * contain the leading null byte, even if it's an abstract namespace socket.
414
+ * @param listenSocketType The type of the listener socket, e.g. "unix" for Unix
415
+ * domain sockets.
294
416
  * @param ownerPipe The owner pipe of this application instance.
295
417
  * @post getAppRoot() == theAppRoot && getPid() == pid
296
418
  */
297
419
  Application(const string &theAppRoot, pid_t pid, const string &listenSocketName,
298
- bool usingAbstractNamespace, int ownerPipe) {
420
+ const string &listenSocketType, int ownerPipe) {
299
421
  appRoot = theAppRoot;
300
422
  this->pid = pid;
301
423
  this->listenSocketName = listenSocketName;
302
- this->usingAbstractNamespace = usingAbstractNamespace;
424
+ this->listenSocketType = listenSocketType;
303
425
  this->ownerPipe = ownerPipe;
304
426
  P_TRACE(3, "Application " << this << ": created.");
305
427
  }
306
428
 
307
429
  virtual ~Application() {
430
+ TRACE_POINT();
308
431
  int ret;
309
432
 
310
433
  if (ownerPipe != -1) {
@@ -312,7 +435,7 @@ public:
312
435
  ret = close(ownerPipe);
313
436
  } while (ret == -1 && errno == EINTR);
314
437
  }
315
- if (!usingAbstractNamespace) {
438
+ if (listenSocketType == "unix") {
316
439
  do {
317
440
  ret = unlink(listenSocketName.c_str());
318
441
  } while (ret == -1 && errno == EINTR);
@@ -384,36 +507,14 @@ public:
384
507
  * @throws IOException Something went wrong during the connection process.
385
508
  */
386
509
  SessionPtr connect(const function<void()> &closeCallback) const {
387
- int fd, ret;
388
-
389
- do {
390
- fd = socket(PF_UNIX, SOCK_STREAM, 0);
391
- } while (fd == -1 && errno == EINTR);
392
- if (fd == -1) {
393
- throw SystemException("Cannot create a new unconnected Unix socket", errno);
394
- }
395
-
396
- struct sockaddr_un addr;
397
- addr.sun_family = AF_UNIX;
398
- if (usingAbstractNamespace) {
399
- strncpy(addr.sun_path + 1, listenSocketName.c_str(), sizeof(addr.sun_path) - 1);
400
- addr.sun_path[0] = '\0';
510
+ TRACE_POINT();
511
+ if (listenSocketType == "unix") {
512
+ return connectToUnixServer(closeCallback);
513
+ } else if (listenSocketType == "tcp") {
514
+ return connectToTcpServer(closeCallback);
401
515
  } else {
402
- strncpy(addr.sun_path, listenSocketName.c_str(), sizeof(addr.sun_path));
403
- }
404
- addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
405
- do {
406
- ret = ::connect(fd, (const sockaddr *) &addr, sizeof(addr));
407
- } while (ret == -1 && errno == EINTR);
408
- if (ret == -1) {
409
- int e = errno;
410
- string message("Cannot connect to Unix socket '");
411
- message.append(listenSocketName);
412
- message.append("' on the abstract namespace");
413
- throw SystemException(message, e);
516
+ throw IOException("Unsupported socket type '" + listenSocketType + "'");
414
517
  }
415
-
416
- return ptr(new StandardSession(pid, closeCallback, fd));
417
518
  }
418
519
  };
419
520
 
@@ -24,6 +24,7 @@
24
24
  #include <sys/types.h>
25
25
 
26
26
  #include "Application.h"
27
+ #include "PoolOptions.h"
27
28
 
28
29
  namespace Passenger {
29
30
 
@@ -91,26 +92,30 @@ public:
91
92
  virtual ~ApplicationPool() {};
92
93
 
93
94
  /**
94
- * Open a new session with the application specified by <tt>appRoot</tt>.
95
+ * Checks whether this ApplicationPool object is still connected to the
96
+ * ApplicationPool server.
97
+ *
98
+ * If that's not the case, then one should reconnect to the ApplicationPool server.
99
+ *
100
+ * This method is only meaningful for instances of type ApplicationPoolServer::Client.
101
+ * The default implementation always returns true.
102
+ */
103
+ virtual bool connected() const {
104
+ return true;
105
+ }
106
+
107
+ /**
108
+ * Open a new session with the application specified by <tt>PoolOptions.appRoot</tt>.
95
109
  * See the class description for ApplicationPool, as well as Application::connect(),
96
110
  * on how to use the returned session object.
97
111
  *
98
112
  * Internally, this method may either spawn a new application instance, or use
99
113
  * an existing one.
100
114
  *
101
- * If <tt>lowerPrivilege</tt> is true, then any newly spawned application
102
- * instances will have lower privileges. See SpawnManager::SpawnManager()'s
103
- * description of <tt>lowerPrivilege</tt> and <tt>lowestUser</tt> for details.
104
- *
105
- * @param appRoot The application root of a RoR application, i.e. the folder that
106
- * contains 'app/', 'public/', 'config/', etc. This must be a valid
107
- * directory, but does not have to be an absolute path.
108
- * @param lowerPrivilege Whether to lower the application's privileges.
109
- * @param lowestUser The user to fallback to if lowering privilege fails.
110
- * @param environment The RAILS_ENV/RACK_ENV environment that should be used. May not be empty.
111
- * @param spawnMethod The spawn method to use. Either "smart" or "conservative".
112
- * See the Ruby class SpawnManager for details.
113
- * @param appType The application type. Either "rails" or "rack".
115
+ * @param options An object containing information on which application to open
116
+ * a session with, as well as spawning details. Spawning details will be used
117
+ * if the pool decides that spawning a new application instance is necessary.
118
+ * See SpawnManager and PoolOptions for details.
114
119
  * @return A session object.
115
120
  * @throw SpawnException An attempt was made to spawn a new application instance, but that attempt failed.
116
121
  * @throw BusyException The application pool is too busy right now, and cannot
@@ -123,9 +128,14 @@ public:
123
128
  * <tt>get("/home/../home/foo")</tt>, then ApplicationPool will think
124
129
  * they're 2 different applications, and thus will spawn 2 application instances.
125
130
  */
126
- virtual Application::SessionPtr get(const string &appRoot, bool lowerPrivilege = true,
127
- const string &lowestUser = "nobody", const string &environment = "production",
128
- const string &spawnMethod = "smart", const string &appType = "rails") = 0;
131
+ virtual Application::SessionPtr get(const PoolOptions &options) = 0;
132
+
133
+ /**
134
+ * Convenience shortcut for calling get() with default spawn options.
135
+ */
136
+ virtual Application::SessionPtr get(const string &appRoot) {
137
+ return get(PoolOptions(appRoot));
138
+ }
129
139
 
130
140
  /**
131
141
  * Clear all application instances that are currently in the pool.
@@ -173,18 +183,6 @@ public:
173
183
  */
174
184
  virtual void setMaxPerApp(unsigned int max) = 0;
175
185
 
176
- /**
177
- * Sets whether to use a global queue instead of a per-backend process
178
- * queue. If enabled, when all backend processes are active, get() will
179
- * wait until there's at least one backend process that's idle, instead
180
- * of queuing the request into a random process's private queue.
181
- * This is especially useful if a website has one or more long-running
182
- * requests.
183
- *
184
- * Defaults to false.
185
- */
186
- virtual void setUseGlobalQueue(bool value) = 0;
187
-
188
186
  /**
189
187
  * Get the process ID of the spawn server that is used.
190
188
  *
@@ -22,6 +22,8 @@
22
22
 
23
23
  #include <boost/shared_ptr.hpp>
24
24
  #include <boost/thread/mutex.hpp>
25
+ #include <oxt/system_calls.hpp>
26
+ #include <oxt/backtrace.hpp>
25
27
 
26
28
  #include <sys/types.h>
27
29
  #include <sys/stat.h>
@@ -40,12 +42,12 @@
40
42
  #include "Application.h"
41
43
  #include "Exceptions.h"
42
44
  #include "Logging.h"
43
- #include "System.h"
44
45
 
45
46
  namespace Passenger {
46
47
 
47
48
  using namespace std;
48
49
  using namespace boost;
50
+ using namespace oxt;
49
51
 
50
52
 
51
53
  /**
@@ -140,16 +142,31 @@ private:
140
142
  /**
141
143
  * The socket connection to the ApplicationPool server, as was
142
144
  * established by ApplicationPoolServer::connect().
145
+ *
146
+ * The value may be -1, which indicates that the connection has
147
+ * been closed.
143
148
  */
144
149
  int server;
145
150
 
146
- mutex lock;
151
+ mutable boost::mutex lock;
147
152
 
148
153
  ~SharedData() {
154
+ TRACE_POINT();
155
+ if (server != -1) {
156
+ disconnect();
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Disconnect from the ApplicationPool server.
162
+ */
163
+ void disconnect() {
164
+ TRACE_POINT();
149
165
  int ret;
150
166
  do {
151
167
  ret = close(server);
152
168
  } while (ret == -1 && errno == EINTR);
169
+ server = -1;
153
170
  }
154
171
  };
155
172
 
@@ -174,7 +191,7 @@ private:
174
191
 
175
192
  virtual ~RemoteSession() {
176
193
  closeStream();
177
- mutex::scoped_lock(data->lock);
194
+ boost::mutex::scoped_lock(data->lock);
178
195
  MessageChannel(data->server).write("close", toString(id).c_str(), NULL);
179
196
  }
180
197
 
@@ -182,9 +199,17 @@ private:
182
199
  return fd;
183
200
  }
184
201
 
202
+ virtual void setReaderTimeout(unsigned int msec) {
203
+ MessageChannel(fd).setReadTimeout(msec);
204
+ }
205
+
206
+ virtual void setWriterTimeout(unsigned int msec) {
207
+ MessageChannel(fd).setWriteTimeout(msec);
208
+ }
209
+
185
210
  virtual void shutdownReader() {
186
211
  if (fd != -1) {
187
- int ret = InterruptableCalls::shutdown(fd, SHUT_RD);
212
+ int ret = syscalls::shutdown(fd, SHUT_RD);
188
213
  if (ret == -1) {
189
214
  throw SystemException("Cannot shutdown the writer stream",
190
215
  errno);
@@ -194,7 +219,7 @@ private:
194
219
 
195
220
  virtual void shutdownWriter() {
196
221
  if (fd != -1) {
197
- int ret = InterruptableCalls::shutdown(fd, SHUT_WR);
222
+ int ret = syscalls::shutdown(fd, SHUT_WR);
198
223
  if (ret == -1) {
199
224
  throw SystemException("Cannot shutdown the writer stream",
200
225
  errno);
@@ -204,7 +229,7 @@ private:
204
229
 
205
230
  virtual void closeStream() {
206
231
  if (fd != -1) {
207
- int ret = InterruptableCalls::close(fd);
232
+ int ret = syscalls::close(fd);
208
233
  if (ret == -1) {
209
234
  throw SystemException("Cannot close the session stream",
210
235
  errno);
@@ -246,112 +271,167 @@ private:
246
271
  data->server = sock;
247
272
  }
248
273
 
274
+ virtual bool connected() const {
275
+ boost::mutex::scoped_lock(data->lock);
276
+ return data->server != -1;
277
+ }
278
+
249
279
  virtual void clear() {
250
280
  MessageChannel channel(data->server);
251
- mutex::scoped_lock l(data->lock);
252
- channel.write("clear", NULL);
281
+ boost::mutex::scoped_lock l(data->lock);
282
+ try {
283
+ channel.write("clear", NULL);
284
+ } catch (...) {
285
+ data->disconnect();
286
+ throw;
287
+ }
253
288
  }
254
289
 
255
290
  virtual void setMaxIdleTime(unsigned int seconds) {
256
291
  MessageChannel channel(data->server);
257
- mutex::scoped_lock l(data->lock);
258
- channel.write("setMaxIdleTime", toString(seconds).c_str(), NULL);
292
+ boost::mutex::scoped_lock l(data->lock);
293
+ try {
294
+ channel.write("setMaxIdleTime", toString(seconds).c_str(), NULL);
295
+ } catch (...) {
296
+ data->disconnect();
297
+ throw;
298
+ }
259
299
  }
260
300
 
261
301
  virtual void setMax(unsigned int max) {
262
302
  MessageChannel channel(data->server);
263
- mutex::scoped_lock l(data->lock);
264
- channel.write("setMax", toString(max).c_str(), NULL);
303
+ boost::mutex::scoped_lock l(data->lock);
304
+ try {
305
+ channel.write("setMax", toString(max).c_str(), NULL);
306
+ } catch (...) {
307
+ data->disconnect();
308
+ throw;
309
+ }
265
310
  }
266
311
 
267
312
  virtual unsigned int getActive() const {
268
313
  MessageChannel channel(data->server);
269
- mutex::scoped_lock l(data->lock);
314
+ boost::mutex::scoped_lock l(data->lock);
270
315
  vector<string> args;
271
316
 
272
- channel.write("getActive", NULL);
273
- channel.read(args);
274
- return atoi(args[0].c_str());
317
+ try {
318
+ channel.write("getActive", NULL);
319
+ channel.read(args);
320
+ return atoi(args[0].c_str());
321
+ } catch (...) {
322
+ data->disconnect();
323
+ throw;
324
+ }
275
325
  }
276
326
 
277
327
  virtual unsigned int getCount() const {
278
328
  MessageChannel channel(data->server);
279
- mutex::scoped_lock l(data->lock);
329
+ boost::mutex::scoped_lock l(data->lock);
280
330
  vector<string> args;
281
331
 
282
- channel.write("getCount", NULL);
283
- channel.read(args);
284
- return atoi(args[0].c_str());
332
+ try {
333
+ channel.write("getCount", NULL);
334
+ channel.read(args);
335
+ return atoi(args[0].c_str());
336
+ } catch (...) {
337
+ data->disconnect();
338
+ throw;
339
+ }
285
340
  }
286
341
 
287
342
  virtual void setMaxPerApp(unsigned int max) {
288
- MessageChannel channel(data->server);
289
- mutex::scoped_lock l(data->lock);
290
- channel.write("setMaxPerApp", toString(max).c_str(), NULL);
291
- }
292
-
293
- virtual void setUseGlobalQueue(bool value) {
294
343
  MessageChannel channel(data->server);
295
344
  boost::mutex::scoped_lock l(data->lock);
296
- channel.write("setUseGlobalQueue", value ? "true" : "false", NULL);
345
+ try {
346
+ channel.write("setMaxPerApp", toString(max).c_str(), NULL);
347
+ } catch (...) {
348
+ data->disconnect();
349
+ throw;
350
+ }
297
351
  }
298
352
 
299
353
  virtual pid_t getSpawnServerPid() const {
300
354
  this_thread::disable_syscall_interruption dsi;
301
355
  MessageChannel channel(data->server);
302
- mutex::scoped_lock l(data->lock);
356
+ boost::mutex::scoped_lock l(data->lock);
303
357
  vector<string> args;
304
358
 
305
- channel.write("getSpawnServerPid", NULL);
306
- channel.read(args);
307
- return atoi(args[0].c_str());
308
- }
309
-
310
- virtual Application::SessionPtr get(
311
- const string &appRoot,
312
- bool lowerPrivilege = true,
313
- const string &lowestUser = "nobody",
314
- const string &environment = "production",
315
- const string &spawnMethod = "smart",
316
- const string &appType = "rails"
317
- ) {
359
+ try {
360
+ channel.write("getSpawnServerPid", NULL);
361
+ channel.read(args);
362
+ return atoi(args[0].c_str());
363
+ } catch (...) {
364
+ data->disconnect();
365
+ throw;
366
+ }
367
+ }
368
+
369
+ virtual Application::SessionPtr get(const PoolOptions &options) {
318
370
  this_thread::disable_syscall_interruption dsi;
371
+ TRACE_POINT();
372
+
319
373
  MessageChannel channel(data->server);
320
- mutex::scoped_lock l(data->lock);
374
+ boost::mutex::scoped_lock l(data->lock);
321
375
  vector<string> args;
322
376
  int stream;
323
377
  bool result;
324
378
 
325
379
  try {
326
- channel.write("get", appRoot.c_str(),
327
- (lowerPrivilege) ? "true" : "false",
328
- lowestUser.c_str(),
329
- environment.c_str(),
330
- spawnMethod.c_str(),
331
- appType.c_str(),
332
- NULL);
333
- } catch (const SystemException &) {
334
- throw IOException("The ApplicationPool server exited unexpectedly.");
380
+ vector<string> args;
381
+
382
+ args.push_back("get");
383
+ options.toVector(args);
384
+ channel.write(args);
385
+ } catch (const SystemException &e) {
386
+ UPDATE_TRACE_POINT();
387
+ data->disconnect();
388
+
389
+ string message("Could not send data to the ApplicationPool server: ");
390
+ message.append(e.brief());
391
+ throw SystemException(message, e.code());
335
392
  }
336
393
  try {
394
+ UPDATE_TRACE_POINT();
337
395
  result = channel.read(args);
338
396
  } catch (const SystemException &e) {
397
+ UPDATE_TRACE_POINT();
398
+ data->disconnect();
339
399
  throw SystemException("Could not read a message from "
340
400
  "the ApplicationPool server", e.code());
341
401
  }
342
402
  if (!result) {
403
+ UPDATE_TRACE_POINT();
404
+ data->disconnect();
343
405
  throw IOException("The ApplicationPool server unexpectedly "
344
406
  "closed the connection.");
345
407
  }
346
408
  if (args[0] == "ok") {
347
- stream = channel.readFileDescriptor();
409
+ UPDATE_TRACE_POINT();
410
+ pid_t pid = (pid_t) atol(args[1]);
411
+ int sessionID = atoi(args[2]);
412
+
413
+ try {
414
+ stream = channel.readFileDescriptor();
415
+ } catch (...) {
416
+ UPDATE_TRACE_POINT();
417
+ data->disconnect();
418
+ throw;
419
+ }
420
+
348
421
  return ptr(new RemoteSession(dataSmartPointer,
349
- atoi(args[1]), atoi(args[2]), stream));
422
+ pid, sessionID, stream));
350
423
  } else if (args[0] == "SpawnException") {
424
+ UPDATE_TRACE_POINT();
351
425
  if (args[2] == "true") {
352
426
  string errorPage;
353
427
 
354
- if (!channel.readScalar(errorPage)) {
428
+ try {
429
+ result = channel.readScalar(errorPage);
430
+ } catch (...) {
431
+ data->disconnect();
432
+ throw;
433
+ }
434
+ if (!result) {
355
435
  throw IOException("The ApplicationPool server "
356
436
  "unexpectedly closed the connection.");
357
437
  }
@@ -360,10 +440,15 @@ private:
360
440
  throw SpawnException(args[1]);
361
441
  }
362
442
  } else if (args[0] == "BusyException") {
443
+ UPDATE_TRACE_POINT();
363
444
  throw BusyException(args[1]);
364
445
  } else if (args[0] == "IOException") {
446
+ UPDATE_TRACE_POINT();
447
+ data->disconnect();
365
448
  throw IOException(args[1]);
366
449
  } else {
450
+ UPDATE_TRACE_POINT();
451
+ data->disconnect();
367
452
  throw IOException("The ApplicationPool server returned "
368
453
  "an unknown message: " + toString(args));
369
454
  }
@@ -408,12 +493,13 @@ private:
408
493
  * @post serverSocket == -1 && serverPid == 0
409
494
  */
410
495
  void shutdownServer() {
496
+ TRACE_POINT();
411
497
  this_thread::disable_syscall_interruption dsi;
412
498
  int ret;
413
499
  time_t begin;
414
500
  bool done = false;
415
501
 
416
- InterruptableCalls::close(serverSocket);
502
+ syscalls::close(serverSocket);
417
503
  if (!statusReportFIFO.empty()) {
418
504
  do {
419
505
  ret = unlink(statusReportFIFO.c_str());
@@ -422,28 +508,28 @@ private:
422
508
 
423
509
  P_TRACE(2, "Waiting for existing ApplicationPoolServerExecutable (PID " <<
424
510
  serverPid << ") to exit...");
425
- begin = InterruptableCalls::time(NULL);
426
- while (!done && InterruptableCalls::time(NULL) < begin + 5) {
511
+ begin = syscalls::time(NULL);
512
+ while (!done && syscalls::time(NULL) < begin + 5) {
427
513
  /*
428
514
  * Some Apache modules fork(), but don't close file descriptors.
429
515
  * mod_wsgi is one such example. Because of that, closing serverSocket
430
516
  * won't always cause the ApplicationPool server to exit. So we send it a
431
517
  * signal.
432
518
  */
433
- InterruptableCalls::kill(serverPid, SIGINT);
519
+ syscalls::kill(serverPid, SIGINT);
434
520
 
435
- ret = InterruptableCalls::waitpid(serverPid, NULL, WNOHANG);
521
+ ret = syscalls::waitpid(serverPid, NULL, WNOHANG);
436
522
  done = ret > 0 || ret == -1;
437
523
  if (!done) {
438
- InterruptableCalls::usleep(100000);
524
+ syscalls::usleep(100000);
439
525
  }
440
526
  }
441
527
  if (done) {
442
528
  P_TRACE(2, "ApplicationPoolServerExecutable exited.");
443
529
  } else {
444
530
  P_DEBUG("ApplicationPoolServerExecutable not exited in time. Killing it...");
445
- InterruptableCalls::kill(serverPid, SIGTERM);
446
- InterruptableCalls::waitpid(serverPid, NULL, 0);
531
+ syscalls::kill(serverPid, SIGTERM);
532
+ syscalls::waitpid(serverPid, NULL, 0);
447
533
  }
448
534
 
449
535
  serverSocket = -1;
@@ -459,6 +545,7 @@ private:
459
545
  * @throw SystemException Something went wrong.
460
546
  */
461
547
  void restartServer() {
548
+ TRACE_POINT();
462
549
  int fds[2];
463
550
  pid_t pid;
464
551
 
@@ -466,14 +553,15 @@ private:
466
553
  shutdownServer();
467
554
  }
468
555
 
469
- if (InterruptableCalls::socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) {
556
+ if (syscalls::socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) {
470
557
  throw SystemException("Cannot create a Unix socket pair", errno);
471
558
  }
472
559
 
473
560
  createStatusReportFIFO();
474
561
 
475
- pid = InterruptableCalls::fork();
562
+ pid = syscalls::fork();
476
563
  if (pid == 0) { // Child process.
564
+ dup2(STDERR_FILENO, STDOUT_FILENO); // Redirect stdout to the same channel as stderr.
477
565
  dup2(fds[0], SERVER_SOCKET_FD);
478
566
 
479
567
  // Close all unnecessary file descriptors
@@ -495,18 +583,20 @@ private:
495
583
  m_rubyCommand.c_str(),
496
584
  m_user.c_str(),
497
585
  statusReportFIFO.c_str(),
498
- NULL);
586
+ (char *) 0);
499
587
  int e = errno;
500
- fprintf(stderr, "*** Passenger ERROR: Cannot execute %s: %s (%d)\n",
588
+ fprintf(stderr, "*** Passenger ERROR (%s:%d):\n"
589
+ "Cannot execute %s: %s (%d)\n",
590
+ __FILE__, __LINE__,
501
591
  m_serverExecutable.c_str(), strerror(e), e);
502
592
  fflush(stderr);
503
593
  _exit(1);
504
594
  } else if (pid == -1) { // Error.
505
- InterruptableCalls::close(fds[0]);
506
- InterruptableCalls::close(fds[1]);
595
+ syscalls::close(fds[0]);
596
+ syscalls::close(fds[1]);
507
597
  throw SystemException("Cannot create a new process", errno);
508
598
  } else { // Parent process.
509
- InterruptableCalls::close(fds[0]);
599
+ syscalls::close(fds[0]);
510
600
  serverSocket = fds[1];
511
601
 
512
602
  int flags = fcntl(serverSocket, F_GETFD);
@@ -519,14 +609,24 @@ private:
519
609
  }
520
610
 
521
611
  void createStatusReportFIFO() {
612
+ TRACE_POINT();
522
613
  char filename[PATH_MAX];
523
614
  int ret;
615
+ mode_t permissions;
616
+
617
+ createPassengerTempDir();
524
618
 
525
- snprintf(filename, sizeof(filename), "/tmp/passenger_status.%d.fifo",
526
- getpid());
619
+ if (m_user.empty()) {
620
+ permissions = S_IRUSR | S_IWUSR;
621
+ } else {
622
+ permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
623
+ }
624
+
625
+ snprintf(filename, sizeof(filename), "%s/status.fifo",
626
+ getPassengerTempDir().c_str());
527
627
  filename[PATH_MAX - 1] = '\0';
528
628
  do {
529
- ret = mkfifo(filename, S_IRUSR | S_IWUSR);
629
+ ret = mkfifo(filename, permissions);
530
630
  } while (ret == -1 && errno == EINTR);
531
631
  if (ret == -1 && errno != EEXIST) {
532
632
  int e = errno;
@@ -536,6 +636,12 @@ private:
536
636
  statusReportFIFO = "";
537
637
  } else {
538
638
  statusReportFIFO = filename;
639
+
640
+ // It seems that the permissions passed to mkfifo()
641
+ // aren't respected, so here we chmod the file.
642
+ do {
643
+ ret = chmod(filename, permissions);
644
+ } while (ret == -1 && errno == EINTR);
539
645
  }
540
646
  }
541
647
 
@@ -572,6 +678,7 @@ public:
572
678
  m_logFile(logFile),
573
679
  m_rubyCommand(rubyCommand),
574
680
  m_user(user) {
681
+ TRACE_POINT();
575
682
  serverSocket = -1;
576
683
  serverPid = 0;
577
684
  this_thread::disable_syscall_interruption dsi;
@@ -579,7 +686,9 @@ public:
579
686
  }
580
687
 
581
688
  ~ApplicationPoolServer() {
689
+ TRACE_POINT();
582
690
  if (serverSocket != -1) {
691
+ UPDATE_TRACE_POINT();
583
692
  this_thread::disable_syscall_interruption dsi;
584
693
  shutdownServer();
585
694
  }
@@ -618,6 +727,7 @@ public:
618
727
  * @throws IOException Something went wrong.
619
728
  */
620
729
  ApplicationPoolPtr connect() {
730
+ TRACE_POINT();
621
731
  try {
622
732
  this_thread::disable_syscall_interruption dsi;
623
733
  MessageChannel channel(serverSocket);
@@ -652,6 +762,7 @@ public:
652
762
  * before calling detach().
653
763
  */
654
764
  void detach() {
765
+ TRACE_POINT();
655
766
  int ret;
656
767
  do {
657
768
  ret = close(serverSocket);