passenger 2.0.3 → 2.0.4

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 (275) hide show
  1. data/Rakefile +8 -5
  2. data/bin/passenger-install-apache2-module +6 -1
  3. data/doc/ApplicationPool algorithm.txt +23 -5
  4. data/doc/Architectural overview.html +778 -0
  5. data/doc/Security of user switching support.html +1 -1
  6. data/doc/Users guide.html +113 -31
  7. data/doc/Users guide.txt +104 -10
  8. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +683 -0
  9. data/doc/cxxapi/ApplicationPool_8h-source.html +224 -0
  10. data/doc/cxxapi/Application_8h-source.html +448 -0
  11. data/doc/cxxapi/Bucket_8h-source.html +61 -0
  12. data/doc/cxxapi/Configuration_8h-source.html +195 -0
  13. data/doc/cxxapi/DummySpawnManager_8h-source.html +126 -0
  14. data/doc/cxxapi/Exceptions_8h-source.html +244 -0
  15. data/doc/cxxapi/Hooks_8h-source.html +63 -0
  16. data/doc/cxxapi/Logging_8h-source.html +136 -0
  17. data/doc/cxxapi/MessageChannel_8h-source.html +524 -0
  18. data/doc/cxxapi/SpawnManager_8h-source.html +593 -0
  19. data/doc/cxxapi/StandardApplicationPool_8h-source.html +732 -0
  20. data/doc/cxxapi/System_8h-source.html +251 -0
  21. data/doc/cxxapi/Utils_8h-source.html +283 -0
  22. data/doc/cxxapi/annotated.html +59 -0
  23. data/doc/cxxapi/classClient-members.html +35 -0
  24. data/doc/cxxapi/classClient.html +117 -0
  25. data/doc/cxxapi/classDirectoryMapper-members.html +38 -0
  26. data/doc/cxxapi/classDirectoryMapper.html +203 -0
  27. data/doc/cxxapi/classHooks-members.html +33 -0
  28. data/doc/cxxapi/classHooks.html +43 -0
  29. data/doc/cxxapi/classPassenger_1_1Application-members.html +38 -0
  30. data/doc/cxxapi/classPassenger_1_1Application.html +229 -0
  31. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +41 -0
  32. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +359 -0
  33. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +36 -0
  34. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +225 -0
  35. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.map +1 -0
  36. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.md5 +1 -0
  37. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
  38. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +43 -0
  39. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +329 -0
  40. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +33 -0
  41. data/doc/cxxapi/classPassenger_1_1BusyException.html +47 -0
  42. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +33 -0
  43. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +44 -0
  44. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +33 -0
  45. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +51 -0
  46. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +33 -0
  47. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +51 -0
  48. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.map +1 -0
  49. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.md5 +1 -0
  50. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
  51. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +38 -0
  52. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +61 -0
  53. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.map +1 -0
  54. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.md5 +1 -0
  55. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
  56. data/doc/cxxapi/classPassenger_1_1IOException-members.html +33 -0
  57. data/doc/cxxapi/classPassenger_1_1IOException.html +54 -0
  58. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.map +1 -0
  59. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.md5 +1 -0
  60. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
  61. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +47 -0
  62. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +591 -0
  63. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +35 -0
  64. data/doc/cxxapi/classPassenger_1_1SpawnException.html +77 -0
  65. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +37 -0
  66. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +255 -0
  67. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +43 -0
  68. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +400 -0
  69. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.map +1 -0
  70. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.md5 +1 -0
  71. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
  72. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +37 -0
  73. data/doc/cxxapi/classPassenger_1_1SystemException.html +154 -0
  74. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.map +1 -0
  75. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.md5 +1 -0
  76. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
  77. data/doc/cxxapi/classPassenger_1_1TempFile-members.html +36 -0
  78. data/doc/cxxapi/classPassenger_1_1TempFile.html +128 -0
  79. data/doc/cxxapi/classPassenger_1_1Thread-members.html +35 -0
  80. data/doc/cxxapi/classPassenger_1_1Thread.html +100 -0
  81. data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption-members.html +33 -0
  82. data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption.html +46 -0
  83. data/doc/cxxapi/classboost_1_1this__thread_1_1enable__syscall__interruption-members.html +33 -0
  84. data/doc/cxxapi/classboost_1_1this__thread_1_1enable__syscall__interruption.html +44 -0
  85. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption-members.html +33 -0
  86. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption.html +44 -0
  87. data/doc/cxxapi/definitions_8h-source.html +28 -0
  88. data/doc/cxxapi/doxygen.css +433 -0
  89. data/doc/cxxapi/doxygen.png +0 -0
  90. data/doc/cxxapi/files.html +42 -0
  91. data/doc/cxxapi/ftv2blank.png +0 -0
  92. data/doc/cxxapi/ftv2doc.png +0 -0
  93. data/doc/cxxapi/ftv2folderclosed.png +0 -0
  94. data/doc/cxxapi/ftv2folderopen.png +0 -0
  95. data/doc/cxxapi/ftv2lastnode.png +0 -0
  96. data/doc/cxxapi/ftv2link.png +0 -0
  97. data/doc/cxxapi/ftv2mlastnode.png +0 -0
  98. data/doc/cxxapi/ftv2mnode.png +0 -0
  99. data/doc/cxxapi/ftv2node.png +0 -0
  100. data/doc/cxxapi/ftv2plastnode.png +0 -0
  101. data/doc/cxxapi/ftv2pnode.png +0 -0
  102. data/doc/cxxapi/ftv2vertline.png +0 -0
  103. data/doc/cxxapi/functions.html +215 -0
  104. data/doc/cxxapi/functions_func.html +210 -0
  105. data/doc/cxxapi/functions_type.html +46 -0
  106. data/doc/cxxapi/functions_vars.html +48 -0
  107. data/doc/cxxapi/graph_legend.dot +22 -0
  108. data/doc/cxxapi/graph_legend.html +87 -0
  109. data/doc/cxxapi/graph_legend.png +0 -0
  110. data/doc/cxxapi/group__Configuration.html +236 -0
  111. data/doc/cxxapi/group__Configuration.png +0 -0
  112. data/doc/cxxapi/group__Core.html +51 -0
  113. data/doc/cxxapi/group__Core.png +0 -0
  114. data/doc/cxxapi/group__Exceptions.html +43 -0
  115. data/doc/cxxapi/group__Hooks.html +46 -0
  116. data/doc/cxxapi/group__Hooks.png +0 -0
  117. data/doc/cxxapi/group__Support.html +406 -0
  118. data/doc/cxxapi/hierarchy.html +67 -0
  119. data/doc/cxxapi/index.html +11 -0
  120. data/doc/cxxapi/inherit__graph__0.map +1 -0
  121. data/doc/cxxapi/inherit__graph__0.md5 +1 -0
  122. data/doc/cxxapi/inherit__graph__0.png +0 -0
  123. data/doc/cxxapi/inherit__graph__1.map +1 -0
  124. data/doc/cxxapi/inherit__graph__1.md5 +1 -0
  125. data/doc/cxxapi/inherit__graph__1.png +0 -0
  126. data/doc/cxxapi/inherit__graph__10.map +1 -0
  127. data/doc/cxxapi/inherit__graph__10.md5 +1 -0
  128. data/doc/cxxapi/inherit__graph__10.png +0 -0
  129. data/doc/cxxapi/inherit__graph__11.map +1 -0
  130. data/doc/cxxapi/inherit__graph__11.md5 +1 -0
  131. data/doc/cxxapi/inherit__graph__11.png +0 -0
  132. data/doc/cxxapi/inherit__graph__12.map +1 -0
  133. data/doc/cxxapi/inherit__graph__12.md5 +1 -0
  134. data/doc/cxxapi/inherit__graph__12.png +0 -0
  135. data/doc/cxxapi/inherit__graph__13.map +1 -0
  136. data/doc/cxxapi/inherit__graph__13.md5 +1 -0
  137. data/doc/cxxapi/inherit__graph__13.png +0 -0
  138. data/doc/cxxapi/inherit__graph__14.map +2 -0
  139. data/doc/cxxapi/inherit__graph__14.md5 +1 -0
  140. data/doc/cxxapi/inherit__graph__14.png +0 -0
  141. data/doc/cxxapi/inherit__graph__15.map +1 -0
  142. data/doc/cxxapi/inherit__graph__15.md5 +1 -0
  143. data/doc/cxxapi/inherit__graph__15.png +0 -0
  144. data/doc/cxxapi/inherit__graph__16.map +1 -0
  145. data/doc/cxxapi/inherit__graph__16.md5 +1 -0
  146. data/doc/cxxapi/inherit__graph__16.png +0 -0
  147. data/doc/cxxapi/inherit__graph__17.map +1 -0
  148. data/doc/cxxapi/inherit__graph__17.md5 +1 -0
  149. data/doc/cxxapi/inherit__graph__17.png +0 -0
  150. data/doc/cxxapi/inherit__graph__18.map +1 -0
  151. data/doc/cxxapi/inherit__graph__18.md5 +1 -0
  152. data/doc/cxxapi/inherit__graph__18.png +0 -0
  153. data/doc/cxxapi/inherit__graph__19.map +2 -0
  154. data/doc/cxxapi/inherit__graph__19.md5 +1 -0
  155. data/doc/cxxapi/inherit__graph__19.png +0 -0
  156. data/doc/cxxapi/inherit__graph__2.map +1 -0
  157. data/doc/cxxapi/inherit__graph__2.md5 +1 -0
  158. data/doc/cxxapi/inherit__graph__2.png +0 -0
  159. data/doc/cxxapi/inherit__graph__20.map +1 -0
  160. data/doc/cxxapi/inherit__graph__20.md5 +1 -0
  161. data/doc/cxxapi/inherit__graph__20.png +0 -0
  162. data/doc/cxxapi/inherit__graph__21.map +1 -0
  163. data/doc/cxxapi/inherit__graph__21.md5 +1 -0
  164. data/doc/cxxapi/inherit__graph__21.png +0 -0
  165. data/doc/cxxapi/inherit__graph__3.map +1 -0
  166. data/doc/cxxapi/inherit__graph__3.md5 +1 -0
  167. data/doc/cxxapi/inherit__graph__3.png +0 -0
  168. data/doc/cxxapi/inherit__graph__4.map +1 -0
  169. data/doc/cxxapi/inherit__graph__4.md5 +1 -0
  170. data/doc/cxxapi/inherit__graph__4.png +0 -0
  171. data/doc/cxxapi/inherit__graph__5.map +1 -0
  172. data/doc/cxxapi/inherit__graph__5.md5 +1 -0
  173. data/doc/cxxapi/inherit__graph__5.png +0 -0
  174. data/doc/cxxapi/inherit__graph__6.map +1 -0
  175. data/doc/cxxapi/inherit__graph__6.md5 +1 -0
  176. data/doc/cxxapi/inherit__graph__6.png +0 -0
  177. data/doc/cxxapi/inherit__graph__7.map +1 -0
  178. data/doc/cxxapi/inherit__graph__7.md5 +1 -0
  179. data/doc/cxxapi/inherit__graph__7.png +0 -0
  180. data/doc/cxxapi/inherit__graph__8.map +1 -0
  181. data/doc/cxxapi/inherit__graph__8.md5 +1 -0
  182. data/doc/cxxapi/inherit__graph__8.png +0 -0
  183. data/doc/cxxapi/inherit__graph__9.map +2 -0
  184. data/doc/cxxapi/inherit__graph__9.md5 +1 -0
  185. data/doc/cxxapi/inherit__graph__9.png +0 -0
  186. data/doc/cxxapi/inherits.html +102 -0
  187. data/doc/cxxapi/main.html +27 -0
  188. data/doc/cxxapi/modules.html +34 -0
  189. data/doc/cxxapi/namespacePassenger.html +208 -0
  190. data/doc/cxxapi/namespacePassenger_1_1InterruptableCalls.html +43 -0
  191. data/doc/cxxapi/namespacemembers.html +70 -0
  192. data/doc/cxxapi/namespacemembers_func.html +66 -0
  193. data/doc/cxxapi/namespacemembers_type.html +46 -0
  194. data/doc/cxxapi/namespaces.html +35 -0
  195. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +33 -0
  196. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +49 -0
  197. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +33 -0
  198. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +49 -0
  199. data/doc/cxxapi/tab_b.gif +0 -0
  200. data/doc/cxxapi/tab_l.gif +0 -0
  201. data/doc/cxxapi/tab_r.gif +0 -0
  202. data/doc/cxxapi/tabs.css +102 -0
  203. data/doc/cxxapi/tree.html +167 -0
  204. data/doc/rdoc/classes/ConditionVariable.html +160 -0
  205. data/doc/rdoc/classes/Exception.html +120 -0
  206. data/doc/rdoc/classes/GC.html +113 -0
  207. data/doc/rdoc/classes/IO.html +150 -0
  208. data/doc/rdoc/classes/Passenger.html +136 -0
  209. data/doc/rdoc/classes/Passenger/AbstractRequestHandler.html +402 -0
  210. data/doc/rdoc/classes/Passenger/AbstractServer.html +649 -0
  211. data/doc/rdoc/classes/Passenger/AbstractServer/ServerAlreadyStarted.html +97 -0
  212. data/doc/rdoc/classes/Passenger/AbstractServer/ServerError.html +96 -0
  213. data/doc/rdoc/classes/Passenger/AbstractServer/ServerNotStarted.html +97 -0
  214. data/doc/rdoc/classes/Passenger/AbstractServer/UnknownMessage.html +96 -0
  215. data/doc/rdoc/classes/Passenger/AppInitError.html +137 -0
  216. data/doc/rdoc/classes/Passenger/Application.html +298 -0
  217. data/doc/rdoc/classes/Passenger/ConsoleTextTemplate.html +172 -0
  218. data/doc/rdoc/classes/Passenger/FrameworkInitError.html +143 -0
  219. data/doc/rdoc/classes/Passenger/HTMLTemplate.html +175 -0
  220. data/doc/rdoc/classes/Passenger/InitializationError.html +141 -0
  221. data/doc/rdoc/classes/Passenger/MessageChannel.html +488 -0
  222. data/doc/rdoc/classes/Passenger/NativeSupport.html +320 -0
  223. data/doc/rdoc/classes/Passenger/SpawnManager.html +375 -0
  224. data/doc/rdoc/classes/Passenger/UnknownError.html +125 -0
  225. data/doc/rdoc/classes/Passenger/Utils.html +578 -0
  226. data/doc/rdoc/classes/Passenger/VersionNotFound.html +140 -0
  227. data/doc/rdoc/classes/PlatformInfo.html +302 -0
  228. data/doc/rdoc/classes/RakeExtensions.html +197 -0
  229. data/doc/rdoc/created.rid +1 -0
  230. data/doc/rdoc/files/DEVELOPERS_TXT.html +230 -0
  231. data/doc/rdoc/files/README.html +150 -0
  232. data/doc/rdoc/files/ext/passenger/native_support_c.html +92 -0
  233. data/doc/rdoc/files/lib/passenger/abstract_request_handler_rb.html +126 -0
  234. data/doc/rdoc/files/lib/passenger/abstract_server_rb.html +127 -0
  235. data/doc/rdoc/files/lib/passenger/application_rb.html +123 -0
  236. data/doc/rdoc/files/lib/passenger/console_text_template_rb.html +122 -0
  237. data/doc/rdoc/files/lib/passenger/constants_rb.html +114 -0
  238. data/doc/rdoc/files/lib/passenger/dependencies_rb.html +130 -0
  239. data/doc/rdoc/files/lib/passenger/exceptions_rb.html +118 -0
  240. data/doc/rdoc/files/lib/passenger/html_template_rb.html +122 -0
  241. data/doc/rdoc/files/lib/passenger/message_channel_rb.html +118 -0
  242. data/doc/rdoc/files/lib/passenger/platform_info_rb.html +122 -0
  243. data/doc/rdoc/files/lib/passenger/simple_benchmarking_rb.html +118 -0
  244. data/doc/rdoc/files/lib/passenger/spawn_manager_rb.html +139 -0
  245. data/doc/rdoc/files/lib/passenger/utils_rb.html +130 -0
  246. data/doc/rdoc/files/lib/rake/extensions_rb.html +122 -0
  247. data/doc/rdoc/fr_class_index.html +71 -0
  248. data/doc/rdoc/fr_file_index.html +63 -0
  249. data/doc/rdoc/fr_method_index.html +120 -0
  250. data/doc/rdoc/index.html +26 -0
  251. data/doc/rdoc/rdoc-style.css +187 -0
  252. data/ext/apache2/ApplicationPool.h +12 -0
  253. data/ext/apache2/ApplicationPoolServer.h +6 -0
  254. data/ext/apache2/ApplicationPoolServerExecutable.cpp +6 -0
  255. data/ext/apache2/Bucket.cpp +63 -69
  256. data/ext/apache2/Bucket.h +2 -0
  257. data/ext/apache2/Configuration.cpp +24 -0
  258. data/ext/apache2/Configuration.h +16 -1
  259. data/ext/apache2/Hooks.cpp +5 -3
  260. data/ext/apache2/StandardApplicationPool.h +30 -11
  261. data/lib/passenger/abstract_request_handler.rb +3 -0
  262. data/lib/passenger/abstract_server.rb +3 -3
  263. data/lib/passenger/application.rb +4 -2
  264. data/lib/passenger/dependencies.rb +10 -1
  265. data/lib/passenger/platform_info.rb +40 -1
  266. data/lib/passenger/rack/request_handler.rb +4 -2
  267. data/lib/passenger/railz/application_spawner.rb +7 -1
  268. data/lib/passenger/utils.rb +6 -8
  269. data/lib/rake/gempackagetask.rb +0 -6
  270. data/lib/rake/rdoctask.rb +84 -23
  271. data/test/ApplicationPoolTest.cpp +36 -0
  272. data/test/ruby/rails/minimal_spawner_spec.rb +8 -0
  273. data/test/ruby/utils_spec.rb +33 -0
  274. data/test/stub/rails_apps/foobar/config/environments/production.rb +0 -1
  275. metadata +262 -5
@@ -636,7 +636,7 @@ feel free to discuss it with us.</p></div>
636
636
  </div>
637
637
  <div id="footer">
638
638
  <div id="footer-text">
639
- Last updated 2008-08-09 14:31:10 CEST
639
+ Last updated 2008-12-01 14:21:18 CEST
640
640
  </div>
641
641
  </div>
642
642
  </body>
@@ -1040,13 +1040,16 @@ run Ramaze::Adapter::Base</tt></pre>
1040
1040
  <div class="content">
1041
1041
  <pre><tt>require 'rubygems'
1042
1042
  require 'sinatra'
1043
+
1044
+ root_dir = File.dirname(__FILE__)
1045
+
1043
1046
  Sinatra::Application.default_options.merge!(
1047
+ :views =&gt; File.join(root_dir, 'views'),
1048
+ :app_file =&gt; File.join(root_dir, 'app.rb'),
1044
1049
  :run =&gt; false,
1045
- :env =&gt; ENV['RACK_ENV']
1050
+ :env =&gt; ENV['RACK_ENV'].to_sym
1046
1051
  )
1047
1052
 
1048
- ### ...your Sinatra application code here... ###
1049
-
1050
1053
  run Sinatra.application</tt></pre>
1051
1054
  </div></div>
1052
1055
  </div>
@@ -1096,18 +1099,95 @@ The default is <em>0</em>.</p></div>
1096
1099
  <div class="para"><p>This option allows one to specify the Ruby interpreter to use.</p></div>
1097
1100
  <div class="para"><p>This option may only occur once, in the global server configuration.
1098
1101
  The default is <em>ruby</em>.</p></div>
1099
- <h3 id="PassengerUserSwitching">5.4. PassengerUserSwitching &lt;on|off&gt;</h3><div style="clear:left"></div>
1102
+ <h3 id="PassengerUseGlobalQueue">5.4. PassengerUseGlobalQueue &lt;on|off&gt;</h3><div style="clear:left"></div>
1103
+ <div class="para"><p>Turns the use of global queuing on or off.</p></div>
1104
+ <div class="para"><p>This option may only occur once, in the global server configuration. The
1105
+ default is <em>off</em>.</p></div>
1106
+ <div class="para"><p><em>This feature is sponsored by <a href="http://www.37signals.com/">37signals</a>.</em></p></div>
1107
+ <div class="para"><div class="title">What does this option do?</div><p>Recall that Phusion Passenger spawns multiple backend processes (e.g. multiple
1108
+ Ruby on Rails processes), each which processes HTTP requests serially. One of
1109
+ Phusion Passenger's jobs is to forward HTTP requests to a suitable backend
1110
+ process. A backend process may take an arbitrary amount of time to process a
1111
+ specific HTTP request. If the websites are (temporarily) under high load, and
1112
+ the backend processes cannot process the requests fast enough, then some
1113
+ requests may have to be queued.</p></div>
1114
+ <div class="para"><p>If global queuing is turned off, then Phusion Passenger will use <em>fair load
1115
+ balancing</em>. This means that each backend process will have its own private
1116
+ queue. Phusion Passenger will forward an HTTP request to the backend process
1117
+ that has the least amount of requests in its queue.</p></div>
1118
+ <div class="para"><p>If global queuing is turned on, then Phusion Passenger will use a global queue
1119
+ that's shared between all backend processes. If an HTTP request comes in, and
1120
+ all the backend processes are still busy, then Phusion Passenger will wait until
1121
+ at least one backend process is done, and will then forward the request to that
1122
+ process.</p></div>
1123
+ <div class="para"><div class="title">When to turn on global queuing?</div><p>You should turn on global queuing if one of your web applications may have
1124
+ long-running requests.</p></div>
1125
+ <div class="para"><p>For example suppose that:</p></div>
1126
+ <div class="ilist"><ul>
1127
+ <li>
1128
+ <p>
1129
+ global queuing is turned off.
1130
+ </p>
1131
+ </li>
1132
+ <li>
1133
+ <p>
1134
+ we're currently in a state where all backend processes have 3 requests in
1135
+ their queue, except for a single backend process, which has 1 request in its
1136
+ queue.
1137
+ </p>
1138
+ </li>
1139
+ </ul></div>
1140
+ <div class="para"><p>The situation looks like this:</p></div>
1141
+ <div class="listingblock">
1142
+ <div class="content">
1143
+ <pre><tt>Backend process A: [* ] (1 request in queue)
1144
+ Backend process B: [*** ] (3 requests in queue)
1145
+ Backend process C: [*** ] (3 requests in queue)
1146
+ Backend process D: [*** ] (3 requests in queue)</tt></pre>
1147
+ </div></div>
1148
+ <div class="para"><p>Each process is currently serving short-running requests.</p></div>
1149
+ <div class="para"><p>Phusion Passenger will forward the next request to backend process A. A will
1150
+ now have 2 items in its queue. We'll mark this new request with an X:</p></div>
1151
+ <div class="listingblock">
1152
+ <div class="content">
1153
+ <pre><tt>Backend process A: [*X ] (2 request in queue)
1154
+ Backend process B: [*** ] (3 requests in queue)
1155
+ Backend process C: [*** ] (3 requests in queue)
1156
+ Backend process D: [*** ] (3 requests in queue)</tt></pre>
1157
+ </div></div>
1158
+ <div class="para"><p>Assuming that B, C and D still aren't done with their current request, the next
1159
+ HTTP request - let's call this Y - will be forwarded to backend process A as
1160
+ well, because it has the least number of items in its queue:</p></div>
1161
+ <div class="listingblock">
1162
+ <div class="content">
1163
+ <pre><tt>Backend process A: [*XY ] (3 requests in queue)
1164
+ Backend process B: [*** ] (3 requests in queue)
1165
+ Backend process C: [*** ] (3 requests in queue)
1166
+ Backend process D: [*** ] (3 requests in queue)</tt></pre>
1167
+ </div></div>
1168
+ <div class="para"><p>But if request X happens to be a long-running request that needs 60 seconds to
1169
+ complete, then we'll have a problem. Y won't be processed for at least 60
1170
+ seconds. It would have been a better idea if Y was forward to processes B, C or
1171
+ D instead, because they only have short-living requests in their queues.</p></div>
1172
+ <div class="para"><p>This problem will be avoided entirely if you turn global queuing on. With global
1173
+ queuing, all backend processes will share the same queue. The first backend
1174
+ process that becomes available will take from the queue, and so this
1175
+ &#8220;queuing-behind-long-running-request&#8221; problem will never occur.</p></div>
1176
+ <div class="para"><p>Turning global queuing off will yield a minor performance improvement (about 5%,
1177
+ depending on how fast/slow your web application is), which is why it's off by
1178
+ default.</p></div>
1179
+ <h3 id="PassengerUserSwitching">5.5. PassengerUserSwitching &lt;on|off&gt;</h3><div style="clear:left"></div>
1100
1180
  <div class="para"><p>Whether to enable <a href="#user_switching">user switching support</a>.</p></div>
1101
1181
  <div class="para"><p>This option may only occur once, in the global server configuration.
1102
1182
  The default value is <em>on</em>.</p></div>
1103
- <h3 id="PassengerDefaultUser">5.5. PassengerDefaultUser &lt;username&gt;</h3><div style="clear:left"></div>
1183
+ <h3 id="PassengerDefaultUser">5.6. PassengerDefaultUser &lt;username&gt;</h3><div style="clear:left"></div>
1104
1184
  <div class="para"><p>Passenger enables <a href="#user_switching">user switching support</a> by default.
1105
1185
  This configuration option allows one to specify which user Rails/Rack
1106
1186
  applications must run as, if user switching fails or is disabled.</p></div>
1107
1187
  <div class="para"><p>This option may only occur once, in the global server configuration.
1108
1188
  The default value is <em>nobody</em>.</p></div>
1109
- <h3 id="_resource_control_and_optimization_options">5.6. Resource control and optimization options</h3><div style="clear:left"></div>
1110
- <h4 id="_passengermaxpoolsize_lt_integer_gt">5.6.1. PassengerMaxPoolSize &lt;integer&gt;</h4>
1189
+ <h3 id="_resource_control_and_optimization_options">5.7. Resource control and optimization options</h3><div style="clear:left"></div>
1190
+ <h4 id="_passengermaxpoolsize_lt_integer_gt">5.7.1. PassengerMaxPoolSize &lt;integer&gt;</h4>
1111
1191
  <div class="para"><p>The maximum number of Ruby on Rails or Rack application instances that may
1112
1192
  be simultaneously active. A larger number results in higher memory usage,
1113
1193
  but improved ability to handle concurrent HTTP clients.</p></div>
@@ -1132,7 +1212,7 @@ The default value is <em>6</em>.</p></div>
1132
1212
  by about 33%. And it's not hard to install.</td>
1133
1213
  </tr></table>
1134
1214
  </div>
1135
- <h4 id="_passengermaxinstancesperapp_lt_integer_gt">5.6.2. PassengerMaxInstancesPerApp &lt;integer&gt;</h4>
1215
+ <h4 id="_passengermaxinstancesperapp_lt_integer_gt">5.7.2. PassengerMaxInstancesPerApp &lt;integer&gt;</h4>
1136
1216
  <div class="para"><p>The maximum number of application instances that may be simultaneously active
1137
1217
  for a single application. This helps to make sure that a single application
1138
1218
  will not occupy all available slots in the application pool.</p></div>
@@ -1142,11 +1222,10 @@ may use, i.e. only the global limit of <a href="#PassengerMaxPoolSize">Passenger
1142
1222
  will be enforced.</p></div>
1143
1223
  <div class="para"><p>This option may only occur once, in the global server configuration.
1144
1224
  The default value is <em>0</em>.</p></div>
1145
- <h4 id="PassengerPoolIdleTime">5.6.3. PassengerPoolIdleTime &lt;integer&gt;</h4>
1146
- <div class="para"><p>The maximum number of seconds that a Ruby on Rails or Rack application instance
1147
- may be idle. That is, if an application instance hasn't done anything after
1148
- the given number of seconds, then it will be shutdown in order to conserve
1149
- memory.</p></div>
1225
+ <h4 id="PassengerPoolIdleTime">5.7.3. PassengerPoolIdleTime &lt;integer&gt;</h4>
1226
+ <div class="para"><p>The maximum number of seconds that an application instance may be idle. That is,
1227
+ if an application instance hasn't received any traffic after the given number of
1228
+ seconds, then it will be shutdown in order to conserve memory.</p></div>
1150
1229
  <div class="para"><p>Decreasing this value means that applications will have to be spawned
1151
1230
  more often. Since spawning is a relatively slow operation, some visitors may
1152
1231
  notice a small delay when they visit your Rails/Rack website. However, it will also
@@ -1157,8 +1236,8 @@ number of seconds that a visitor spends on a single Rails/Rack web page. But you
1157
1236
  mileage may vary.</p></div>
1158
1237
  <div class="para"><p>This option may only occur once, in the global server configuration.
1159
1238
  The default value is <em>300</em>.</p></div>
1160
- <h3 id="_ruby_on_rails_specific_options">5.7. Ruby on Rails-specific options</h3><div style="clear:left"></div>
1161
- <h4 id="_railsautodetect_lt_on_off_gt">5.7.1. RailsAutoDetect &lt;on|off&gt;</h4>
1239
+ <h3 id="_ruby_on_rails_specific_options">5.8. Ruby on Rails-specific options</h3><div style="clear:left"></div>
1240
+ <h4 id="_railsautodetect_lt_on_off_gt">5.8.1. RailsAutoDetect &lt;on|off&gt;</h4>
1162
1241
  <div class="para"><p>Whether Phusion Passenger should automatically detect whether a virtual host's
1163
1242
  document root is a Ruby on Rails application. The default is <em>on</em>.</p></div>
1164
1243
  <div class="para"><p>This option may occur in the global server configuration or in a virtual host
@@ -1186,23 +1265,23 @@ application by using the <a href="#RailsBaseURI">RailsBaseURI</a> configuration
1186
1265
  RailsBaseURI / # This line has been added.
1187
1266
  &lt;/VirtualHost&gt;</tt></pre>
1188
1267
  </div></div>
1189
- <h4 id="RailsBaseURI">5.7.2. RailsBaseURI &lt;uri&gt;</h4>
1268
+ <h4 id="RailsBaseURI">5.8.2. RailsBaseURI &lt;uri&gt;</h4>
1190
1269
  <div class="para"><p>Used to specify that the given URI is a Rails application. See
1191
1270
  <a href="#deploying_rails_to_sub_uri">Deploying Rails to a sub URI</a> for an example.</p></div>
1192
1271
  <div class="para"><p>It is allowed to specify this option multiple times. Do this to deploy multiple
1193
1272
  Rails applications in different sub-URIs under the same virtual host.</p></div>
1194
1273
  <div class="para"><p>This option may occur in the global server configuration or in a
1195
1274
  virtual host configuration block.</p></div>
1196
- <h4 id="RailsAllowModRewrite">5.7.3. RailsAllowModRewrite &lt;on|off&gt;</h4>
1275
+ <h4 id="RailsAllowModRewrite">5.8.3. RailsAllowModRewrite &lt;on|off&gt;</h4>
1197
1276
  <div class="para"><p>If enabled, Phusion Passenger will not override mod_rewrite rules. Please read
1198
1277
  <a href="#conflicting_apache_modules">Conflicting Apache modules</a> for details.</p></div>
1199
1278
  <div class="para"><p>This option may occur once, in the global server configuration or in a virtual host
1200
1279
  configuration block. The default value is <em>off</em>.</p></div>
1201
- <h4 id="rails_env">5.7.4. RailsEnv &lt;string&gt;</h4>
1280
+ <h4 id="rails_env">5.8.4. RailsEnv &lt;string&gt;</h4>
1202
1281
  <div class="para"><p>This option allows one to specify the default <tt>RAILS_ENV</tt> value.</p></div>
1203
1282
  <div class="para"><p>This option may occur once, in the global server configuration or in a virtual host
1204
1283
  configuration block. The default value is <em>production</em>.</p></div>
1205
- <h4 id="RailsSpawnMethod">5.7.5. RailsSpawnMethod &lt;string&gt;</h4>
1284
+ <h4 id="RailsSpawnMethod">5.8.5. RailsSpawnMethod &lt;string&gt;</h4>
1206
1285
  <div class="admonitionblock">
1207
1286
  <table><tr>
1208
1287
  <td class="icon">
@@ -1227,7 +1306,7 @@ requests. But there are multiple ways with which processes can be spawned, each
1227
1306
  its own set of pros and cons. Supported spawn methods are:</p></div>
1228
1307
  <div class="vlist"><dl>
1229
1308
  <dt>
1230
- smart
1309
+ <em>smart</em>
1231
1310
  </dt>
1232
1311
  <dd>
1233
1312
  <p>
@@ -1243,7 +1322,7 @@ If that's the case for your application, then you should use <em>conservative</e
1243
1322
  spawning method.</p></div>
1244
1323
  </dd>
1245
1324
  <dt>
1246
- conservative
1325
+ <em>conservative</em>
1247
1326
  </dt>
1248
1327
  <dd>
1249
1328
  <p>
@@ -1251,7 +1330,8 @@ This spawning method is similar to the one used in Mongrel Cluster. It does not
1251
1330
  any code caching at all.
1252
1331
  </p>
1253
1332
  <div class="para"><p><strong>Pros:</strong>
1254
- Conservative spawning is guaranteed to be compatible with all applications and libraries.</p></div>
1333
+ Conservative spawning is guaranteed to be compatible with all Rails applications
1334
+ and libraries.</p></div>
1255
1335
  <div class="para"><p><strong>Cons:</strong>
1256
1336
  Much slower than smart spawning. Every spawn action will be equally slow, though no slower than
1257
1337
  the startup time of a single server in Mongrel Cluster. Conservative spawning will also
@@ -1260,8 +1340,8 @@ render <a href="#reducing_memory_usage">Ruby Enterprise Edition's memory reducti
1260
1340
  </dl></div>
1261
1341
  <div class="para"><p>This option may occur once, in the global server configuration or in a virtual host
1262
1342
  configuration block. The default value is <em>smart</em>.</p></div>
1263
- <h3 id="_rack_specific_options">5.8. Rack-specific options</h3><div style="clear:left"></div>
1264
- <h4 id="_rackautodetect_lt_on_off_gt">5.8.1. RackAutoDetect &lt;on|off&gt;</h4>
1343
+ <h3 id="_rack_specific_options">5.9. Rack-specific options</h3><div style="clear:left"></div>
1344
+ <h4 id="_rackautodetect_lt_on_off_gt">5.9.1. RackAutoDetect &lt;on|off&gt;</h4>
1265
1345
  <div class="para"><p>Whether Phusion Passenger should automatically detect whether a virtual host's
1266
1346
  document root is a Rack application. The default is <em>on</em>.</p></div>
1267
1347
  <div class="para"><p>This option may occur in the global server configuration or in a virtual host
@@ -1289,27 +1369,27 @@ application by using the <a href="#RackBaseURI">RackBaseURI</a> configuration op
1289
1369
  RackBaseURI / # This line was added
1290
1370
  &lt;/VirtualHost&gt;</tt></pre>
1291
1371
  </div></div>
1292
- <h4 id="RackBaseURI">5.8.2. RackBaseURI &lt;uri&gt;</h4>
1372
+ <h4 id="RackBaseURI">5.9.2. RackBaseURI &lt;uri&gt;</h4>
1293
1373
  <div class="para"><p>Used to specify that the given URI is a Rack application. See
1294
1374
  <a href="#deploying_rack_to_sub_uri">Deploying Rack to a sub URI</a> for an example.</p></div>
1295
1375
  <div class="para"><p>It is allowed to specify this option multiple times. Do this to deploy multiple
1296
1376
  Rack applications in different sub-URIs under the same virtual host.</p></div>
1297
1377
  <div class="para"><p>This option may occur in the global server configuration or in a
1298
1378
  virtual host configuration block.</p></div>
1299
- <h4 id="rack_env">5.8.3. RackEnv &lt;string&gt;</h4>
1379
+ <h4 id="rack_env">5.9.3. RackEnv &lt;string&gt;</h4>
1300
1380
  <div class="para"><p>The given value will be accessible in Rack applications in the <tt>RACK_ENV</tt>
1301
1381
  environment variable. This allows one to define the environment in which
1302
1382
  Rack applications are run, very similar to <tt>RAILS_ENV</tt>.</p></div>
1303
1383
  <div class="para"><p>This option may occur once, in the global server configuration or in a virtual host
1304
1384
  configuration block. The default value is <em>production</em>.</p></div>
1305
- <h3 id="_deprecated_options">5.9. Deprecated options</h3><div style="clear:left"></div>
1385
+ <h3 id="_deprecated_options">5.10. Deprecated options</h3><div style="clear:left"></div>
1306
1386
  <div class="para"><p>The following options have been deprecated, but are still supported for backwards
1307
1387
  compatibility reasons.</p></div>
1308
- <h4 id="_railsruby">5.9.1. RailsRuby</h4>
1388
+ <h4 id="_railsruby">5.10.1. RailsRuby</h4>
1309
1389
  <div class="para"><p>Deprecated in favor of <a href="#PassengerRuby">PassengerRuby</a>.</p></div>
1310
- <h4 id="_railsuserswitching">5.9.2. RailsUserSwitching</h4>
1390
+ <h4 id="_railsuserswitching">5.10.2. RailsUserSwitching</h4>
1311
1391
  <div class="para"><p>Deprecated in favor of <a href="#PassengerUserSwitching">PassengerUserSwitching</a>.</p></div>
1312
- <h4 id="_railsdefaultuser">5.9.3. RailsDefaultUser</h4>
1392
+ <h4 id="_railsdefaultuser">5.10.3. RailsDefaultUser</h4>
1313
1393
  <div class="para"><p>Deprecated in favor of <a href="#PassengerDefaultUser">PassengerDefaultUser</a>.</p></div>
1314
1394
  </div>
1315
1395
  <h2 id="_troubleshooting">6. Troubleshooting</h2>
@@ -1890,6 +1970,8 @@ sessions compared to the others, then there might be a problem:</p></div>
1890
1970
  <li>
1891
1971
  <p>
1892
1972
  Your application is busy processing a request that takes a very long time.
1973
+ If this is the case, then you might want to turn
1974
+ <a href="#PassengerUseGlobalQueue">global queuing</a> on.
1893
1975
  </p>
1894
1976
  </li>
1895
1977
  <li>
@@ -2097,7 +2179,7 @@ Attribution-Share Alike 3.0 Unported License</a>.</p></div>
2097
2179
  </div>
2098
2180
  <div id="footer">
2099
2181
  <div id="footer-text">
2100
- Last updated 2008-08-09 14:31:11 CEST
2182
+ Last updated 2008-12-01 14:21:18 CEST
2101
2183
  </div>
2102
2184
  </div>
2103
2185
  </body>
@@ -493,13 +493,16 @@ run Ramaze::Adapter::Base
493
493
  ------------------------------------------------------
494
494
  require 'rubygems'
495
495
  require 'sinatra'
496
+
497
+ root_dir = File.dirname(__FILE__)
498
+
496
499
  Sinatra::Application.default_options.merge!(
500
+ :views => File.join(root_dir, 'views'),
501
+ :app_file => File.join(root_dir, 'app.rb'),
497
502
  :run => false,
498
- :env => ENV['RACK_ENV']
503
+ :env => ENV['RACK_ENV'].to_sym
499
504
  )
500
505
 
501
- ### ...your Sinatra application code here... ###
502
-
503
506
  run Sinatra.application
504
507
  ------------------------------------------------------
505
508
 
@@ -542,6 +545,95 @@ This option allows one to specify the Ruby interpreter to use.
542
545
  This option may only occur once, in the global server configuration.
543
546
  The default is 'ruby'.
544
547
 
548
+ [[PassengerUseGlobalQueue]]
549
+ === PassengerUseGlobalQueue <on|off> ===
550
+ Turns the use of global queuing on or off.
551
+
552
+ This option may only occur once, in the global server configuration. The
553
+ default is 'off'.
554
+
555
+ 'This feature is sponsored by http://www.37signals.com/[37signals].'
556
+
557
+ .What does this option do?
558
+
559
+ Recall that Phusion Passenger spawns multiple backend processes (e.g. multiple
560
+ Ruby on Rails processes), each which processes HTTP requests serially. One of
561
+ Phusion Passenger's jobs is to forward HTTP requests to a suitable backend
562
+ process. A backend process may take an arbitrary amount of time to process a
563
+ specific HTTP request. If the websites are (temporarily) under high load, and
564
+ the backend processes cannot process the requests fast enough, then some
565
+ requests may have to be queued.
566
+
567
+ If global queuing is turned off, then Phusion Passenger will use 'fair load
568
+ balancing'. This means that each backend process will have its own private
569
+ queue. Phusion Passenger will forward an HTTP request to the backend process
570
+ that has the least amount of requests in its queue.
571
+
572
+ If global queuing is turned on, then Phusion Passenger will use a global queue
573
+ that's shared between all backend processes. If an HTTP request comes in, and
574
+ all the backend processes are still busy, then Phusion Passenger will wait until
575
+ at least one backend process is done, and will then forward the request to that
576
+ process.
577
+
578
+ .When to turn on global queuing?
579
+
580
+ You should turn on global queuing if one of your web applications may have
581
+ long-running requests.
582
+
583
+ For example suppose that:
584
+
585
+ - global queuing is turned off.
586
+ - we're currently in a state where all backend processes have 3 requests in
587
+ their queue, except for a single backend process, which has 1 request in its
588
+ queue.
589
+
590
+ The situation looks like this:
591
+
592
+ --------------------------------------------------
593
+ Backend process A: [* ] (1 request in queue)
594
+ Backend process B: [*** ] (3 requests in queue)
595
+ Backend process C: [*** ] (3 requests in queue)
596
+ Backend process D: [*** ] (3 requests in queue)
597
+ --------------------------------------------------
598
+
599
+ Each process is currently serving short-running requests.
600
+
601
+ Phusion Passenger will forward the next request to backend process A. A will
602
+ now have 2 items in its queue. We'll mark this new request with an X:
603
+
604
+ --------------------------------------------------
605
+ Backend process A: [*X ] (2 request in queue)
606
+ Backend process B: [*** ] (3 requests in queue)
607
+ Backend process C: [*** ] (3 requests in queue)
608
+ Backend process D: [*** ] (3 requests in queue)
609
+ --------------------------------------------------
610
+
611
+ Assuming that B, C and D still aren't done with their current request, the next
612
+ HTTP request - let's call this Y - will be forwarded to backend process A as
613
+ well, because it has the least number of items in its queue:
614
+
615
+ --------------------------------------------------
616
+ Backend process A: [*XY ] (3 requests in queue)
617
+ Backend process B: [*** ] (3 requests in queue)
618
+ Backend process C: [*** ] (3 requests in queue)
619
+ Backend process D: [*** ] (3 requests in queue)
620
+ --------------------------------------------------
621
+
622
+ But if request X happens to be a long-running request that needs 60 seconds to
623
+ complete, then we'll have a problem. Y won't be processed for at least 60
624
+ seconds. It would have been a better idea if Y was forward to processes B, C or
625
+ D instead, because they only have short-living requests in their queues.
626
+
627
+ This problem will be avoided entirely if you turn global queuing on. With global
628
+ queuing, all backend processes will share the same queue. The first backend
629
+ process that becomes available will take from the queue, and so this
630
+ ``queuing-behind-long-running-request'' problem will never occur.
631
+
632
+ Turning global queuing off will yield a minor performance improvement (about 5%,
633
+ depending on how fast/slow your web application is), which is why it's off by
634
+ default.
635
+
636
+
545
637
  [[PassengerUserSwitching]]
546
638
  === PassengerUserSwitching <on|off> ===
547
639
  Whether to enable <<user_switching,user switching support>>.
@@ -599,10 +691,9 @@ The default value is '0'.
599
691
 
600
692
  [[PassengerPoolIdleTime]]
601
693
  ==== PassengerPoolIdleTime <integer> ====
602
- The maximum number of seconds that a Ruby on Rails or Rack application instance
603
- may be idle. That is, if an application instance hasn't done anything after
604
- the given number of seconds, then it will be shutdown in order to conserve
605
- memory.
694
+ The maximum number of seconds that an application instance may be idle. That is,
695
+ if an application instance hasn't received any traffic after the given number of
696
+ seconds, then it will be shutdown in order to conserve memory.
606
697
 
607
698
  Decreasing this value means that applications will have to be spawned
608
699
  more often. Since spawning is a relatively slow operation, some visitors may
@@ -699,7 +790,7 @@ Internally, Phusion Passenger spawns multiple Ruby on Rails processes in order t
699
790
  requests. But there are multiple ways with which processes can be spawned, each having
700
791
  its own set of pros and cons. Supported spawn methods are:
701
792
 
702
- smart::
793
+ 'smart'::
703
794
  When this spawn method is used, Phusion Passenger will attempt to cache Ruby on Rails
704
795
  framework code and application code for a limited period of time.
705
796
  +
@@ -712,12 +803,13 @@ Some Ruby on Rails applications and libraries are not compatible with smart spaw
712
803
  If that's the case for your application, then you should use 'conservative' as
713
804
  spawning method.
714
805
 
715
- conservative::
806
+ 'conservative'::
716
807
  This spawning method is similar to the one used in Mongrel Cluster. It does not perform
717
808
  any code caching at all.
718
809
  +
719
810
  *Pros:*
720
- Conservative spawning is guaranteed to be compatible with all applications and libraries.
811
+ Conservative spawning is guaranteed to be compatible with all Rails applications
812
+ and libraries.
721
813
  +
722
814
  *Cons:*
723
815
  Much slower than smart spawning. Every spawn action will be equally slow, though no slower than
@@ -1254,6 +1346,8 @@ sessions compared to the others, then there might be a problem:
1254
1346
  Possible reasons why spikes can occur:
1255
1347
 
1256
1348
  . Your application is busy processing a request that takes a very long time.
1349
+ If this is the case, then you might want to turn
1350
+ <<PassengerUseGlobalQueue,global queuing>> on.
1257
1351
  . Your application is frozen, i.e. has stopped responding. See
1258
1352
  <<debugging_frozen,Debugging frozen applications>> for tips.
1259
1353
 
@@ -0,0 +1,683 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
+ <html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
3
+ <title>Passenger: ApplicationPoolServer.h Source File</title>
4
+ <link href="doxygen.css" rel="stylesheet" type="text/css">
5
+ <link href="tabs.css" rel="stylesheet" type="text/css">
6
+ </head><body>
7
+ <!-- Generated by Doxygen 1.5.5 -->
8
+ <div class="navigation" id="top">
9
+ <div class="tabs">
10
+ <ul>
11
+ <li><a href="main.html"><span>Main&nbsp;Page</span></a></li>
12
+ <li><a href="modules.html"><span>Modules</span></a></li>
13
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
14
+ <li><a href="annotated.html"><span>Classes</span></a></li>
15
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
16
+ </ul>
17
+ </div>
18
+ <h1>ApplicationPoolServer.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
19
+ <a name="l00002"></a>00002 <span class="comment"> * Phusion Passenger - http://www.modrails.com/</span>
20
+ <a name="l00003"></a>00003 <span class="comment"> * Copyright (C) 2008 Phusion</span>
21
+ <a name="l00004"></a>00004 <span class="comment"> *</span>
22
+ <a name="l00005"></a>00005 <span class="comment"> * Phusion Passenger is a trademark of Hongli Lai &amp; Ninh Bui.</span>
23
+ <a name="l00006"></a>00006 <span class="comment"> *</span>
24
+ <a name="l00007"></a>00007 <span class="comment"> * This program is free software; you can redistribute it and/or modify</span>
25
+ <a name="l00008"></a>00008 <span class="comment"> * it under the terms of the GNU General Public License as published by</span>
26
+ <a name="l00009"></a>00009 <span class="comment"> * the Free Software Foundation; version 2 of the License.</span>
27
+ <a name="l00010"></a>00010 <span class="comment"> *</span>
28
+ <a name="l00011"></a>00011 <span class="comment"> * This program is distributed in the hope that it will be useful,</span>
29
+ <a name="l00012"></a>00012 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
30
+ <a name="l00013"></a>00013 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
31
+ <a name="l00014"></a>00014 <span class="comment"> * GNU General Public License for more details.</span>
32
+ <a name="l00015"></a>00015 <span class="comment"> *</span>
33
+ <a name="l00016"></a>00016 <span class="comment"> * You should have received a copy of the GNU General Public License along</span>
34
+ <a name="l00017"></a>00017 <span class="comment"> * with this program; if not, write to the Free Software Foundation, Inc.,</span>
35
+ <a name="l00018"></a>00018 <span class="comment"> * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span>
36
+ <a name="l00019"></a>00019 <span class="comment"> */</span>
37
+ <a name="l00020"></a>00020 <span class="preprocessor">#ifndef _PASSENGER_APPLICATION_POOL_SERVER_H_</span>
38
+ <a name="l00021"></a>00021 <span class="preprocessor"></span><span class="preprocessor">#define _PASSENGER_APPLICATION_POOL_SERVER_H_</span>
39
+ <a name="l00022"></a>00022 <span class="preprocessor"></span>
40
+ <a name="l00023"></a>00023 <span class="preprocessor">#include &lt;boost/shared_ptr.hpp&gt;</span>
41
+ <a name="l00024"></a>00024 <span class="preprocessor">#include &lt;boost/thread/mutex.hpp&gt;</span>
42
+ <a name="l00025"></a>00025
43
+ <a name="l00026"></a>00026 <span class="preprocessor">#include &lt;sys/types.h&gt;</span>
44
+ <a name="l00027"></a>00027 <span class="preprocessor">#include &lt;sys/stat.h&gt;</span>
45
+ <a name="l00028"></a>00028 <span class="preprocessor">#include &lt;sys/wait.h&gt;</span>
46
+ <a name="l00029"></a>00029 <span class="preprocessor">#include &lt;sys/socket.h&gt;</span>
47
+ <a name="l00030"></a>00030 <span class="preprocessor">#include &lt;cstdio&gt;</span>
48
+ <a name="l00031"></a>00031 <span class="preprocessor">#include &lt;cstdlib&gt;</span>
49
+ <a name="l00032"></a>00032 <span class="preprocessor">#include &lt;limits.h&gt;</span>
50
+ <a name="l00033"></a>00033 <span class="preprocessor">#include &lt;errno.h&gt;</span>
51
+ <a name="l00034"></a>00034 <span class="preprocessor">#include &lt;unistd.h&gt;</span>
52
+ <a name="l00035"></a>00035 <span class="preprocessor">#include &lt;signal.h&gt;</span>
53
+ <a name="l00036"></a>00036
54
+ <a name="l00037"></a>00037 <span class="preprocessor">#include "MessageChannel.h"</span>
55
+ <a name="l00038"></a>00038 <span class="preprocessor">#include "ApplicationPool.h"</span>
56
+ <a name="l00039"></a>00039 <span class="preprocessor">#include "Application.h"</span>
57
+ <a name="l00040"></a>00040 <span class="preprocessor">#include "Exceptions.h"</span>
58
+ <a name="l00041"></a>00041 <span class="preprocessor">#include "Logging.h"</span>
59
+ <a name="l00042"></a>00042 <span class="preprocessor">#include "System.h"</span>
60
+ <a name="l00043"></a>00043
61
+ <a name="l00044"></a>00044 <span class="keyword">namespace </span>Passenger {
62
+ <a name="l00045"></a>00045
63
+ <a name="l00046"></a>00046 <span class="keyword">using namespace </span>std;
64
+ <a name="l00047"></a>00047 <span class="keyword">using namespace </span>boost;
65
+ <a name="l00048"></a>00048
66
+ <a name="l00049"></a>00049 <span class="comment"></span>
67
+ <a name="l00050"></a>00050 <span class="comment">/**</span>
68
+ <a name="l00051"></a>00051 <span class="comment"> * Multi-process usage support for ApplicationPool.</span>
69
+ <a name="l00052"></a>00052 <span class="comment"> *</span>
70
+ <a name="l00053"></a>00053 <span class="comment"> * ApplicationPoolServer implements a client/server architecture for ApplicationPool.</span>
71
+ <a name="l00054"></a>00054 <span class="comment"> * This allows one to use ApplicationPool in a multi-process environment (unlike</span>
72
+ <a name="l00055"></a>00055 <span class="comment"> * StandardApplicationPool). The cache/pool data is stored in the server. Different</span>
73
+ <a name="l00056"></a>00056 <span class="comment"> * processes can then access the pool through the server.</span>
74
+ <a name="l00057"></a>00057 <span class="comment"> *</span>
75
+ <a name="l00058"></a>00058 <span class="comment"> * ApplicationPoolServer itself does not inherit ApplicationPool. Instead, it returns</span>
76
+ <a name="l00059"></a>00059 <span class="comment"> * an ApplicationPool object via the connect() call. For example:</span>
77
+ <a name="l00060"></a>00060 <span class="comment"> * @code</span>
78
+ <a name="l00061"></a>00061 <span class="comment"> * // Create an ApplicationPoolServer.</span>
79
+ <a name="l00062"></a>00062 <span class="comment"> * ApplicationPoolServer server(...);</span>
80
+ <a name="l00063"></a>00063 <span class="comment"> * </span>
81
+ <a name="l00064"></a>00064 <span class="comment"> * // Now fork a child process, like Apache's prefork MPM eventually will.</span>
82
+ <a name="l00065"></a>00065 <span class="comment"> * pid_t pid = fork();</span>
83
+ <a name="l00066"></a>00066 <span class="comment"> * if (pid == 0) {</span>
84
+ <a name="l00067"></a>00067 <span class="comment"> * // Child process</span>
85
+ <a name="l00068"></a>00068 <span class="comment"> * </span>
86
+ <a name="l00069"></a>00069 <span class="comment"> * // Connect to the server. After connection, we have an ApplicationPool</span>
87
+ <a name="l00070"></a>00070 <span class="comment"> * // object!</span>
88
+ <a name="l00071"></a>00071 <span class="comment"> * ApplicationPoolPtr pool(server.connect());</span>
89
+ <a name="l00072"></a>00072 <span class="comment"> *</span>
90
+ <a name="l00073"></a>00073 <span class="comment"> * // We don't need to connect to the server anymore, so we detach from it.</span>
91
+ <a name="l00074"></a>00074 <span class="comment"> * // This frees up some resources, such as file descriptors.</span>
92
+ <a name="l00075"></a>00075 <span class="comment"> * server.detach();</span>
93
+ <a name="l00076"></a>00076 <span class="comment"> *</span>
94
+ <a name="l00077"></a>00077 <span class="comment"> * ApplicationPool::SessionPtr session(pool-&gt;get("/home/webapps/foo"));</span>
95
+ <a name="l00078"></a>00078 <span class="comment"> * do_something_with(session);</span>
96
+ <a name="l00079"></a>00079 <span class="comment"> *</span>
97
+ <a name="l00080"></a>00080 <span class="comment"> * _exit(0);</span>
98
+ <a name="l00081"></a>00081 <span class="comment"> * } else {</span>
99
+ <a name="l00082"></a>00082 <span class="comment"> * // Parent process</span>
100
+ <a name="l00083"></a>00083 <span class="comment"> * waitpid(pid, NULL, 0);</span>
101
+ <a name="l00084"></a>00084 <span class="comment"> * }</span>
102
+ <a name="l00085"></a>00085 <span class="comment"> * @endcode</span>
103
+ <a name="l00086"></a>00086 <span class="comment"> *</span>
104
+ <a name="l00087"></a>00087 <span class="comment"> * &lt;h2&gt;Implementation notes&lt;/h2&gt;</span>
105
+ <a name="l00088"></a>00088 <span class="comment"> *</span>
106
+ <a name="l00089"></a>00089 <span class="comment"> * &lt;h3&gt;Separate server executable&lt;/h3&gt;</span>
107
+ <a name="l00090"></a>00090 <span class="comment"> * The actual server is implemented in ApplicationPoolServerExecutable.cpp, this class is</span>
108
+ <a name="l00091"></a>00091 <span class="comment"> * just a convenience class for starting/stopping the server executable and connecting</span>
109
+ <a name="l00092"></a>00092 <span class="comment"> * to it.</span>
110
+ <a name="l00093"></a>00093 <span class="comment"> *</span>
111
+ <a name="l00094"></a>00094 <span class="comment"> * In the past, the server logic itself was implemented in this class. This implies that</span>
112
+ <a name="l00095"></a>00095 <span class="comment"> * the ApplicationPool server ran inside the Apache process. This presented us with several</span>
113
+ <a name="l00096"></a>00096 <span class="comment"> * problems:</span>
114
+ <a name="l00097"></a>00097 <span class="comment"> * - Because of the usage of threads in the ApplicationPool server, the Apache VM size would</span>
115
+ <a name="l00098"></a>00098 <span class="comment"> * go way up. This gave people the (wrong) impression that Passenger uses a lot of memory,</span>
116
+ <a name="l00099"></a>00099 <span class="comment"> * or that it leaks memory.</span>
117
+ <a name="l00100"></a>00100 <span class="comment"> * - Although it's not entirely confirmed, we suspect that it caused heap fragmentation as</span>
118
+ <a name="l00101"></a>00101 <span class="comment"> * well. Apache allocates lots and lots of small objects on the heap, and ApplicationPool</span>
119
+ <a name="l00102"></a>00102 <span class="comment"> * server isn't exactly helping. This too gave people the (wrong) impression that</span>
120
+ <a name="l00103"></a>00103 <span class="comment"> * Passenger leaks memory.</span>
121
+ <a name="l00104"></a>00104 <span class="comment"> * - It would unnecessarily bloat the VM size of Apache worker processes.</span>
122
+ <a name="l00105"></a>00105 <span class="comment"> * - We had to resort to all kinds of tricks to make sure that fork()ing a process doesn't</span>
123
+ <a name="l00106"></a>00106 <span class="comment"> * result in file descriptor leaks.</span>
124
+ <a name="l00107"></a>00107 <span class="comment"> * - Despite everything, there was still a small chance that file descriptor leaks would</span>
125
+ <a name="l00108"></a>00108 <span class="comment"> * occur, and this could not be fixed. The reason for this is that the Apache control</span>
126
+ <a name="l00109"></a>00109 <span class="comment"> * process may call fork() right after the ApplicationPool server has established a new</span>
127
+ <a name="l00110"></a>00110 <span class="comment"> * connection with a client.</span>
128
+ <a name="l00111"></a>00111 <span class="comment"> *</span>
129
+ <a name="l00112"></a>00112 <span class="comment"> * Because of these problems, it was decided to split the ApplicationPool server to a</span>
130
+ <a name="l00113"></a>00113 <span class="comment"> * separate executable. This comes with no performance hit.</span>
131
+ <a name="l00114"></a>00114 <span class="comment"> *</span>
132
+ <a name="l00115"></a>00115 <span class="comment"> * &lt;h3&gt;Anonymous server socket&lt;/h3&gt;</span>
133
+ <a name="l00116"></a>00116 <span class="comment"> * Notice that ApplicationPoolServer does do not use TCP sockets at all, or even named Unix</span>
134
+ <a name="l00117"></a>00117 <span class="comment"> * sockets, despite being a server that can handle multiple clients! So ApplicationPoolServer</span>
135
+ <a name="l00118"></a>00118 <span class="comment"> * will expose no open ports or temporary Unix socket files. Only child processes are able</span>
136
+ <a name="l00119"></a>00119 <span class="comment"> * to use the ApplicationPoolServer.</span>
137
+ <a name="l00120"></a>00120 <span class="comment"> *</span>
138
+ <a name="l00121"></a>00121 <span class="comment"> * This is implemented through anonymous Unix sockets (&lt;tt&gt;socketpair()&lt;/tt&gt;) and file descriptor</span>
139
+ <a name="l00122"></a>00122 <span class="comment"> * passing. It allows one to emulate &lt;tt&gt;accept()&lt;/tt&gt;. ApplicationPoolServer is connected to</span>
140
+ <a name="l00123"></a>00123 <span class="comment"> * the server executable through a Unix socket pair. connect() sends a connect request to the</span>
141
+ <a name="l00124"></a>00124 <span class="comment"> * server through that socket. The server will then create a new socket pair, and pass one of</span>
142
+ <a name="l00125"></a>00125 <span class="comment"> * them back. This new socket pair represents the newly established connection.</span>
143
+ <a name="l00126"></a>00126 <span class="comment"> *</span>
144
+ <a name="l00127"></a>00127 <span class="comment"> * @ingroup Support</span>
145
+ <a name="l00128"></a>00128 <span class="comment"> */</span>
146
+ <a name="l00129"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html">00129</a> <span class="keyword">class </span><a class="code" href="classPassenger_1_1ApplicationPoolServer.html" title="Multi-process usage support for ApplicationPool.">ApplicationPoolServer</a> {
147
+ <a name="l00130"></a>00130 <span class="keyword">private</span>:<span class="comment"></span>
148
+ <a name="l00131"></a>00131 <span class="comment"> /**</span>
149
+ <a name="l00132"></a>00132 <span class="comment"> * Contains data shared between RemoteSession and Client.</span>
150
+ <a name="l00133"></a>00133 <span class="comment"> * Since RemoteSession and Client have different life times, i.e. one may be</span>
151
+ <a name="l00134"></a>00134 <span class="comment"> * destroyed before the other, they both use a smart pointer that points to</span>
152
+ <a name="l00135"></a>00135 <span class="comment"> * a SharedData. This way, the SharedData object is only destroyed when</span>
153
+ <a name="l00136"></a>00136 <span class="comment"> * both the RemoteSession and the Client object has been destroyed.</span>
154
+ <a name="l00137"></a>00137 <span class="comment"> */</span>
155
+ <a name="l00138"></a>00138 <span class="keyword">struct </span>SharedData {<span class="comment"></span>
156
+ <a name="l00139"></a>00139 <span class="comment"> /**</span>
157
+ <a name="l00140"></a>00140 <span class="comment"> * The socket connection to the ApplicationPool server, as was</span>
158
+ <a name="l00141"></a>00141 <span class="comment"> * established by ApplicationPoolServer::connect().</span>
159
+ <a name="l00142"></a>00142 <span class="comment"> */</span>
160
+ <a name="l00143"></a>00143 <span class="keywordtype">int</span> server;
161
+ <a name="l00144"></a>00144
162
+ <a name="l00145"></a>00145 mutex lock;
163
+ <a name="l00146"></a>00146
164
+ <a name="l00147"></a>00147 ~SharedData() {
165
+ <a name="l00148"></a>00148 <span class="keywordtype">int</span> ret;
166
+ <a name="l00149"></a>00149 <span class="keywordflow">do</span> {
167
+ <a name="l00150"></a>00150 ret = close(server);
168
+ <a name="l00151"></a>00151 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; errno == EINTR);
169
+ <a name="l00152"></a>00152 }
170
+ <a name="l00153"></a>00153 };
171
+ <a name="l00154"></a>00154
172
+ <a name="l00155"></a>00155 <span class="keyword">typedef</span> shared_ptr&lt;SharedData&gt; SharedDataPtr;
173
+ <a name="l00156"></a>00156 <span class="comment"></span>
174
+ <a name="l00157"></a>00157 <span class="comment"> /**</span>
175
+ <a name="l00158"></a>00158 <span class="comment"> * An Application::Session which works together with ApplicationPoolServer.</span>
176
+ <a name="l00159"></a>00159 <span class="comment"> */</span>
177
+ <a name="l00160"></a>00160 <span class="keyword">class </span>RemoteSession: <span class="keyword">public</span> <a class="code" href="classPassenger_1_1Application.html" title="Represents a single Ruby on Rails or Rack application instance.">Application</a>::Session {
178
+ <a name="l00161"></a>00161 <span class="keyword">private</span>:
179
+ <a name="l00162"></a>00162 SharedDataPtr data;
180
+ <a name="l00163"></a>00163 <span class="keywordtype">int</span> id;
181
+ <a name="l00164"></a>00164 <span class="keywordtype">int</span> fd;
182
+ <a name="l00165"></a>00165 pid_t pid;
183
+ <a name="l00166"></a>00166 <span class="keyword">public</span>:
184
+ <a name="l00167"></a>00167 RemoteSession(SharedDataPtr data, pid_t pid, <span class="keywordtype">int</span> <span class="keywordtype">id</span>, <span class="keywordtype">int</span> fd) {
185
+ <a name="l00168"></a>00168 this-&gt;data = data;
186
+ <a name="l00169"></a>00169 this-&gt;pid = pid;
187
+ <a name="l00170"></a>00170 this-&gt;<span class="keywordtype">id</span> = id;
188
+ <a name="l00171"></a>00171 this-&gt;fd = fd;
189
+ <a name="l00172"></a>00172 }
190
+ <a name="l00173"></a>00173
191
+ <a name="l00174"></a>00174 <span class="keyword">virtual</span> ~RemoteSession() {
192
+ <a name="l00175"></a>00175 closeStream();
193
+ <a name="l00176"></a>00176 mutex::scoped_lock(data-&gt;lock);
194
+ <a name="l00177"></a>00177 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a>(data-&gt;server).write(<span class="stringliteral">"close"</span>, <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(<span class="keywordtype">id</span>).c_str(), NULL);
195
+ <a name="l00178"></a>00178 }
196
+ <a name="l00179"></a>00179
197
+ <a name="l00180"></a>00180 <span class="keyword">virtual</span> <span class="keywordtype">int</span> getStream()<span class="keyword"> const </span>{
198
+ <a name="l00181"></a>00181 <span class="keywordflow">return</span> fd;
199
+ <a name="l00182"></a>00182 }
200
+ <a name="l00183"></a>00183
201
+ <a name="l00184"></a>00184 <span class="keyword">virtual</span> <span class="keywordtype">void</span> shutdownReader() {
202
+ <a name="l00185"></a>00185 <span class="keywordflow">if</span> (fd != -1) {
203
+ <a name="l00186"></a>00186 <span class="keywordtype">int</span> ret = InterruptableCalls::shutdown(fd, SHUT_RD);
204
+ <a name="l00187"></a>00187 <span class="keywordflow">if</span> (ret == -1) {
205
+ <a name="l00188"></a>00188 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot shutdown the writer stream"</span>,
206
+ <a name="l00189"></a>00189 errno);
207
+ <a name="l00190"></a>00190 }
208
+ <a name="l00191"></a>00191 }
209
+ <a name="l00192"></a>00192 }
210
+ <a name="l00193"></a>00193
211
+ <a name="l00194"></a>00194 <span class="keyword">virtual</span> <span class="keywordtype">void</span> shutdownWriter() {
212
+ <a name="l00195"></a>00195 <span class="keywordflow">if</span> (fd != -1) {
213
+ <a name="l00196"></a>00196 <span class="keywordtype">int</span> ret = InterruptableCalls::shutdown(fd, SHUT_WR);
214
+ <a name="l00197"></a>00197 <span class="keywordflow">if</span> (ret == -1) {
215
+ <a name="l00198"></a>00198 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot shutdown the writer stream"</span>,
216
+ <a name="l00199"></a>00199 errno);
217
+ <a name="l00200"></a>00200 }
218
+ <a name="l00201"></a>00201 }
219
+ <a name="l00202"></a>00202 }
220
+ <a name="l00203"></a>00203
221
+ <a name="l00204"></a>00204 <span class="keyword">virtual</span> <span class="keywordtype">void</span> closeStream() {
222
+ <a name="l00205"></a>00205 <span class="keywordflow">if</span> (fd != -1) {
223
+ <a name="l00206"></a>00206 <span class="keywordtype">int</span> ret = InterruptableCalls::close(fd);
224
+ <a name="l00207"></a>00207 <span class="keywordflow">if</span> (ret == -1) {
225
+ <a name="l00208"></a>00208 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot close the session stream"</span>,
226
+ <a name="l00209"></a>00209 errno);
227
+ <a name="l00210"></a>00210 }
228
+ <a name="l00211"></a>00211 fd = -1;
229
+ <a name="l00212"></a>00212 }
230
+ <a name="l00213"></a>00213 }
231
+ <a name="l00214"></a>00214
232
+ <a name="l00215"></a>00215 <span class="keyword">virtual</span> <span class="keywordtype">void</span> discardStream() {
233
+ <a name="l00216"></a>00216 fd = -1;
234
+ <a name="l00217"></a>00217 }
235
+ <a name="l00218"></a>00218
236
+ <a name="l00219"></a>00219 <span class="keyword">virtual</span> pid_t getPid()<span class="keyword"> const </span>{
237
+ <a name="l00220"></a>00220 <span class="keywordflow">return</span> pid;
238
+ <a name="l00221"></a>00221 }
239
+ <a name="l00222"></a>00222 };
240
+ <a name="l00223"></a>00223 <span class="comment"></span>
241
+ <a name="l00224"></a>00224 <span class="comment"> /**</span>
242
+ <a name="l00225"></a>00225 <span class="comment"> * An ApplicationPool implementation that works together with ApplicationPoolServer.</span>
243
+ <a name="l00226"></a>00226 <span class="comment"> * It doesn't do much by itself, its job is mostly to forward queries/commands to</span>
244
+ <a name="l00227"></a>00227 <span class="comment"> * the server and returning the result. Most of the logic is in the server executable.</span>
245
+ <a name="l00228"></a>00228 <span class="comment"> */</span>
246
+ <a name="l00229"></a>00229 <span class="keyword">class </span><a class="code" href="classClient.html#e625bb32c95bde75bfa4bdfdb8ee56db" title="Create a new Client object.">Client</a>: <span class="keyword">public</span> <a class="code" href="classPassenger_1_1ApplicationPool.html" title="A persistent pool of Applications.">ApplicationPool</a> {
247
+ <a name="l00230"></a>00230 <span class="keyword">private</span>:
248
+ <a name="l00231"></a>00231 <span class="comment">// The smart pointer only serves to keep the shared data alive.</span>
249
+ <a name="l00232"></a>00232 <span class="comment">// We access the shared data via a normal pointer, for performance.</span>
250
+ <a name="l00233"></a>00233 SharedDataPtr dataSmartPointer;
251
+ <a name="l00234"></a>00234 SharedData *data;
252
+ <a name="l00235"></a>00235
253
+ <a name="l00236"></a>00236 <span class="keyword">public</span>:<span class="comment"></span>
254
+ <a name="l00237"></a>00237 <span class="comment"> /**</span>
255
+ <a name="l00238"></a>00238 <span class="comment"> * Create a new Client.</span>
256
+ <a name="l00239"></a>00239 <span class="comment"> *</span>
257
+ <a name="l00240"></a>00240 <span class="comment"> * @param sock The newly established socket connection with the ApplicationPoolServer.</span>
258
+ <a name="l00241"></a>00241 <span class="comment"> */</span>
259
+ <a name="l00242"></a>00242 Client(<span class="keywordtype">int</span> sock) {
260
+ <a name="l00243"></a>00243 dataSmartPointer = <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(<span class="keyword">new</span> SharedData());
261
+ <a name="l00244"></a>00244 data = dataSmartPointer.get();
262
+ <a name="l00245"></a>00245 data-&gt;server = sock;
263
+ <a name="l00246"></a>00246 }
264
+ <a name="l00247"></a>00247
265
+ <a name="l00248"></a>00248 <span class="keyword">virtual</span> <span class="keywordtype">void</span> clear() {
266
+ <a name="l00249"></a>00249 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
267
+ <a name="l00250"></a>00250 mutex::scoped_lock l(data-&gt;lock);
268
+ <a name="l00251"></a>00251 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#9ad7a978cf8409e01ab2f0a2b6be5a0a" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"clear"</span>, NULL);
269
+ <a name="l00252"></a>00252 }
270
+ <a name="l00253"></a>00253
271
+ <a name="l00254"></a>00254 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMaxIdleTime(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> seconds) {
272
+ <a name="l00255"></a>00255 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
273
+ <a name="l00256"></a>00256 mutex::scoped_lock l(data-&gt;lock);
274
+ <a name="l00257"></a>00257 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#9ad7a978cf8409e01ab2f0a2b6be5a0a" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"setMaxIdleTime"</span>, <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(seconds).c_str(), NULL);
275
+ <a name="l00258"></a>00258 }
276
+ <a name="l00259"></a>00259
277
+ <a name="l00260"></a>00260 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMax(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> max) {
278
+ <a name="l00261"></a>00261 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
279
+ <a name="l00262"></a>00262 mutex::scoped_lock l(data-&gt;lock);
280
+ <a name="l00263"></a>00263 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#9ad7a978cf8409e01ab2f0a2b6be5a0a" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"setMax"</span>, <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(max).c_str(), NULL);
281
+ <a name="l00264"></a>00264 }
282
+ <a name="l00265"></a>00265
283
+ <a name="l00266"></a>00266 <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> getActive()<span class="keyword"> const </span>{
284
+ <a name="l00267"></a>00267 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
285
+ <a name="l00268"></a>00268 mutex::scoped_lock l(data-&gt;lock);
286
+ <a name="l00269"></a>00269 vector&lt;string&gt; args;
287
+ <a name="l00270"></a>00270
288
+ <a name="l00271"></a>00271 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#9ad7a978cf8409e01ab2f0a2b6be5a0a" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"getActive"</span>, NULL);
289
+ <a name="l00272"></a>00272 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args);
290
+ <a name="l00273"></a>00273 <span class="keywordflow">return</span> <a class="code" href="group__Support.html#g73b17b509ee44938a56bf16cbf82fb48" title="Converts the given string to an integer.">atoi</a>(args[0].c_str());
291
+ <a name="l00274"></a>00274 }
292
+ <a name="l00275"></a>00275
293
+ <a name="l00276"></a>00276 <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> getCount()<span class="keyword"> const </span>{
294
+ <a name="l00277"></a>00277 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
295
+ <a name="l00278"></a>00278 mutex::scoped_lock l(data-&gt;lock);
296
+ <a name="l00279"></a>00279 vector&lt;string&gt; args;
297
+ <a name="l00280"></a>00280
298
+ <a name="l00281"></a>00281 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#9ad7a978cf8409e01ab2f0a2b6be5a0a" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"getCount"</span>, NULL);
299
+ <a name="l00282"></a>00282 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args);
300
+ <a name="l00283"></a>00283 <span class="keywordflow">return</span> <a class="code" href="group__Support.html#g73b17b509ee44938a56bf16cbf82fb48" title="Converts the given string to an integer.">atoi</a>(args[0].c_str());
301
+ <a name="l00284"></a>00284 }
302
+ <a name="l00285"></a>00285
303
+ <a name="l00286"></a>00286 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMaxPerApp(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> max) {
304
+ <a name="l00287"></a>00287 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
305
+ <a name="l00288"></a>00288 mutex::scoped_lock l(data-&gt;lock);
306
+ <a name="l00289"></a>00289 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#9ad7a978cf8409e01ab2f0a2b6be5a0a" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"setMaxPerApp"</span>, <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(max).c_str(), NULL);
307
+ <a name="l00290"></a>00290 }
308
+ <a name="l00291"></a>00291
309
+ <a name="l00292"></a>00292 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setUseGlobalQueue(<span class="keywordtype">bool</span> value) {
310
+ <a name="l00293"></a>00293 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
311
+ <a name="l00294"></a>00294 boost::mutex::scoped_lock l(data-&gt;lock);
312
+ <a name="l00295"></a>00295 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#9ad7a978cf8409e01ab2f0a2b6be5a0a" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"setUseGlobalQueue"</span>, value ? <span class="stringliteral">"true"</span> : <span class="stringliteral">"false"</span>, NULL);
313
+ <a name="l00296"></a>00296 }
314
+ <a name="l00297"></a>00297
315
+ <a name="l00298"></a>00298 <span class="keyword">virtual</span> pid_t getSpawnServerPid()<span class="keyword"> const </span>{
316
+ <a name="l00299"></a>00299 <a class="code" href="classboost_1_1this__thread_1_1disable__syscall__interruption.html" title="Create this struct on the stack to temporarily disable system call interruption,...">this_thread::disable_syscall_interruption</a> dsi;
317
+ <a name="l00300"></a>00300 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
318
+ <a name="l00301"></a>00301 mutex::scoped_lock l(data-&gt;lock);
319
+ <a name="l00302"></a>00302 vector&lt;string&gt; args;
320
+ <a name="l00303"></a>00303
321
+ <a name="l00304"></a>00304 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#9ad7a978cf8409e01ab2f0a2b6be5a0a" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"getSpawnServerPid"</span>, NULL);
322
+ <a name="l00305"></a>00305 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args);
323
+ <a name="l00306"></a>00306 <span class="keywordflow">return</span> <a class="code" href="group__Support.html#g73b17b509ee44938a56bf16cbf82fb48" title="Converts the given string to an integer.">atoi</a>(args[0].c_str());
324
+ <a name="l00307"></a>00307 }
325
+ <a name="l00308"></a>00308
326
+ <a name="l00309"></a>00309 <span class="keyword">virtual</span> <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a> <span class="keyword">get</span>(
327
+ <a name="l00310"></a>00310 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot,
328
+ <a name="l00311"></a>00311 <span class="keywordtype">bool</span> lowerPrivilege = <span class="keyword">true</span>,
329
+ <a name="l00312"></a>00312 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;lowestUser = <span class="stringliteral">"nobody"</span>,
330
+ <a name="l00313"></a>00313 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;environment = <span class="stringliteral">"production"</span>,
331
+ <a name="l00314"></a>00314 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;spawnMethod = <span class="stringliteral">"smart"</span>,
332
+ <a name="l00315"></a>00315 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appType = <span class="stringliteral">"rails"</span>
333
+ <a name="l00316"></a>00316 ) {
334
+ <a name="l00317"></a>00317 <a class="code" href="classboost_1_1this__thread_1_1disable__syscall__interruption.html" title="Create this struct on the stack to temporarily disable system call interruption,...">this_thread::disable_syscall_interruption</a> dsi;
335
+ <a name="l00318"></a>00318 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
336
+ <a name="l00319"></a>00319 mutex::scoped_lock l(data-&gt;lock);
337
+ <a name="l00320"></a>00320 vector&lt;string&gt; args;
338
+ <a name="l00321"></a>00321 <span class="keywordtype">int</span> stream;
339
+ <a name="l00322"></a>00322 <span class="keywordtype">bool</span> result;
340
+ <a name="l00323"></a>00323
341
+ <a name="l00324"></a>00324 <span class="keywordflow">try</span> {
342
+ <a name="l00325"></a>00325 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#9ad7a978cf8409e01ab2f0a2b6be5a0a" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"get"</span>, appRoot.c_str(),
343
+ <a name="l00326"></a>00326 (lowerPrivilege) ? <span class="stringliteral">"true"</span> : <span class="stringliteral">"false"</span>,
344
+ <a name="l00327"></a>00327 lowestUser.c_str(),
345
+ <a name="l00328"></a>00328 environment.c_str(),
346
+ <a name="l00329"></a>00329 spawnMethod.c_str(),
347
+ <a name="l00330"></a>00330 appType.c_str(),
348
+ <a name="l00331"></a>00331 NULL);
349
+ <a name="l00332"></a>00332 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a> &amp;) {
350
+ <a name="l00333"></a>00333 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"The ApplicationPool server exited unexpectedly."</span>);
351
+ <a name="l00334"></a>00334 }
352
+ <a name="l00335"></a>00335 <span class="keywordflow">try</span> {
353
+ <a name="l00336"></a>00336 result = channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args);
354
+ <a name="l00337"></a>00337 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a> &amp;e) {
355
+ <a name="l00338"></a>00338 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Could not read a message from "</span>
356
+ <a name="l00339"></a>00339 <span class="stringliteral">"the ApplicationPool server"</span>, e.<a class="code" href="classPassenger_1_1SystemException.html#ee7a6672bf79b72a4c3ee70c57d6a47c" title="The value of errno at the time the error occured.">code</a>());
357
+ <a name="l00340"></a>00340 }
358
+ <a name="l00341"></a>00341 <span class="keywordflow">if</span> (!result) {
359
+ <a name="l00342"></a>00342 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"The ApplicationPool server unexpectedly "</span>
360
+ <a name="l00343"></a>00343 <span class="stringliteral">"closed the connection."</span>);
361
+ <a name="l00344"></a>00344 }
362
+ <a name="l00345"></a>00345 <span class="keywordflow">if</span> (args[0] == <span class="stringliteral">"ok"</span>) {
363
+ <a name="l00346"></a>00346 stream = channel.<a class="code" href="classPassenger_1_1MessageChannel.html#1561b7e4a0f4d39ea431f456e5655488" title="Receive a file descriptor, which had been passed over the underlying file descriptor...">readFileDescriptor</a>();
364
+ <a name="l00347"></a>00347 <span class="keywordflow">return</span> <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(<span class="keyword">new</span> RemoteSession(dataSmartPointer,
365
+ <a name="l00348"></a>00348 <a class="code" href="group__Support.html#g73b17b509ee44938a56bf16cbf82fb48" title="Converts the given string to an integer.">atoi</a>(args[1]), <a class="code" href="group__Support.html#g73b17b509ee44938a56bf16cbf82fb48" title="Converts the given string to an integer.">atoi</a>(args[2]), stream));
366
+ <a name="l00349"></a>00349 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (args[0] == <span class="stringliteral">"SpawnException"</span>) {
367
+ <a name="l00350"></a>00350 <span class="keywordflow">if</span> (args[2] == <span class="stringliteral">"true"</span>) {
368
+ <a name="l00351"></a>00351 <span class="keywordtype">string</span> errorPage;
369
+ <a name="l00352"></a>00352
370
+ <a name="l00353"></a>00353 <span class="keywordflow">if</span> (!channel.<a class="code" href="classPassenger_1_1MessageChannel.html#4ce6a0e751b5e3563bee583c231569bc" title="Read a scalar message from the underlying file descriptor.">readScalar</a>(errorPage)) {
371
+ <a name="l00354"></a>00354 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"The ApplicationPool server "</span>
372
+ <a name="l00355"></a>00355 <span class="stringliteral">"unexpectedly closed the connection."</span>);
373
+ <a name="l00356"></a>00356 }
374
+ <a name="l00357"></a>00357 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SpawnException.html" title="Thrown when SpawnManager or ApplicationPool fails to spawn an application instance...">SpawnException</a>(args[1], errorPage);
375
+ <a name="l00358"></a>00358 } <span class="keywordflow">else</span> {
376
+ <a name="l00359"></a>00359 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SpawnException.html" title="Thrown when SpawnManager or ApplicationPool fails to spawn an application instance...">SpawnException</a>(args[1]);
377
+ <a name="l00360"></a>00360 }
378
+ <a name="l00361"></a>00361 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (args[0] == <span class="stringliteral">"BusyException"</span>) {
379
+ <a name="l00362"></a>00362 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1BusyException.html" title="The application pool is too busy and cannot fulfill a get() request.">BusyException</a>(args[1]);
380
+ <a name="l00363"></a>00363 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (args[0] == <span class="stringliteral">"IOException"</span>) {
381
+ <a name="l00364"></a>00364 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(args[1]);
382
+ <a name="l00365"></a>00365 } <span class="keywordflow">else</span> {
383
+ <a name="l00366"></a>00366 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"The ApplicationPool server returned "</span>
384
+ <a name="l00367"></a>00367 <span class="stringliteral">"an unknown message: "</span> + <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(args));
385
+ <a name="l00368"></a>00368 }
386
+ <a name="l00369"></a>00369 }
387
+ <a name="l00370"></a>00370 };
388
+ <a name="l00371"></a>00371
389
+ <a name="l00372"></a>00372
390
+ <a name="l00373"></a>00373 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> SERVER_SOCKET_FD = 3;
391
+ <a name="l00374"></a>00374
392
+ <a name="l00375"></a>00375 <span class="keywordtype">string</span> m_serverExecutable;
393
+ <a name="l00376"></a>00376 <span class="keywordtype">string</span> m_spawnServerCommand;
394
+ <a name="l00377"></a>00377 <span class="keywordtype">string</span> m_logFile;
395
+ <a name="l00378"></a>00378 <span class="keywordtype">string</span> m_rubyCommand;
396
+ <a name="l00379"></a>00379 <span class="keywordtype">string</span> m_user;
397
+ <a name="l00380"></a>00380 <span class="keywordtype">string</span> statusReportFIFO;
398
+ <a name="l00381"></a>00381 <span class="comment"></span>
399
+ <a name="l00382"></a>00382 <span class="comment"> /**</span>
400
+ <a name="l00383"></a>00383 <span class="comment"> * The PID of the ApplicationPool server process. If no server process</span>
401
+ <a name="l00384"></a>00384 <span class="comment"> * is running, then &lt;tt&gt;serverPid == 0&lt;/tt&gt;.</span>
402
+ <a name="l00385"></a>00385 <span class="comment"> *</span>
403
+ <a name="l00386"></a>00386 <span class="comment"> * @invariant</span>
404
+ <a name="l00387"></a>00387 <span class="comment"> * if serverPid == 0:</span>
405
+ <a name="l00388"></a>00388 <span class="comment"> * serverSocket == -1</span>
406
+ <a name="l00389"></a>00389 <span class="comment"> */</span>
407
+ <a name="l00390"></a>00390 pid_t serverPid;
408
+ <a name="l00391"></a>00391 <span class="comment"></span>
409
+ <a name="l00392"></a>00392 <span class="comment"> /**</span>
410
+ <a name="l00393"></a>00393 <span class="comment"> * The connection to the ApplicationPool server process. If no server</span>
411
+ <a name="l00394"></a>00394 <span class="comment"> * process is running, then &lt;tt&gt;serverSocket == -1&lt;/tt&gt;.</span>
412
+ <a name="l00395"></a>00395 <span class="comment"> *</span>
413
+ <a name="l00396"></a>00396 <span class="comment"> * @invariant</span>
414
+ <a name="l00397"></a>00397 <span class="comment"> * if serverPid == 0:</span>
415
+ <a name="l00398"></a>00398 <span class="comment"> * serverSocket == -1</span>
416
+ <a name="l00399"></a>00399 <span class="comment"> */</span>
417
+ <a name="l00400"></a>00400 <span class="keywordtype">int</span> serverSocket;
418
+ <a name="l00401"></a>00401 <span class="comment"></span>
419
+ <a name="l00402"></a>00402 <span class="comment"> /**</span>
420
+ <a name="l00403"></a>00403 <span class="comment"> * Shutdown the currently running ApplicationPool server process.</span>
421
+ <a name="l00404"></a>00404 <span class="comment"> *</span>
422
+ <a name="l00405"></a>00405 <span class="comment"> * @pre System call interruption is disabled.</span>
423
+ <a name="l00406"></a>00406 <span class="comment"> * @pre serverSocket != -1 &amp;&amp; serverPid != 0</span>
424
+ <a name="l00407"></a>00407 <span class="comment"> * @post serverSocket == -1 &amp;&amp; serverPid == 0</span>
425
+ <a name="l00408"></a>00408 <span class="comment"> */</span>
426
+ <a name="l00409"></a>00409 <span class="keywordtype">void</span> shutdownServer() {
427
+ <a name="l00410"></a>00410 <a class="code" href="classboost_1_1this__thread_1_1disable__syscall__interruption.html" title="Create this struct on the stack to temporarily disable system call interruption,...">this_thread::disable_syscall_interruption</a> dsi;
428
+ <a name="l00411"></a>00411 <span class="keywordtype">int</span> ret;
429
+ <a name="l00412"></a>00412 time_t begin;
430
+ <a name="l00413"></a>00413 <span class="keywordtype">bool</span> done = <span class="keyword">false</span>;
431
+ <a name="l00414"></a>00414
432
+ <a name="l00415"></a>00415 InterruptableCalls::close(serverSocket);
433
+ <a name="l00416"></a>00416 <span class="keywordflow">if</span> (!statusReportFIFO.empty()) {
434
+ <a name="l00417"></a>00417 <span class="keywordflow">do</span> {
435
+ <a name="l00418"></a>00418 ret = unlink(statusReportFIFO.c_str());
436
+ <a name="l00419"></a>00419 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; errno == EINTR);
437
+ <a name="l00420"></a>00420 }
438
+ <a name="l00421"></a>00421
439
+ <a name="l00422"></a>00422 P_TRACE(2, <span class="stringliteral">"Waiting for existing ApplicationPoolServerExecutable (PID "</span> &lt;&lt;
440
+ <a name="l00423"></a>00423 serverPid &lt;&lt; <span class="stringliteral">") to exit..."</span>);
441
+ <a name="l00424"></a>00424 begin = InterruptableCalls::time(NULL);
442
+ <a name="l00425"></a>00425 <span class="keywordflow">while</span> (!done &amp;&amp; InterruptableCalls::time(NULL) &lt; begin + 5) {
443
+ <a name="l00426"></a>00426 <span class="comment">/*</span>
444
+ <a name="l00427"></a>00427 <span class="comment"> * Some Apache modules fork(), but don't close file descriptors.</span>
445
+ <a name="l00428"></a>00428 <span class="comment"> * mod_wsgi is one such example. Because of that, closing serverSocket</span>
446
+ <a name="l00429"></a>00429 <span class="comment"> * won't always cause the ApplicationPool server to exit. So we send it a</span>
447
+ <a name="l00430"></a>00430 <span class="comment"> * signal.</span>
448
+ <a name="l00431"></a>00431 <span class="comment"> */</span>
449
+ <a name="l00432"></a>00432 InterruptableCalls::kill(serverPid, SIGINT);
450
+ <a name="l00433"></a>00433
451
+ <a name="l00434"></a>00434 ret = InterruptableCalls::waitpid(serverPid, NULL, WNOHANG);
452
+ <a name="l00435"></a>00435 done = ret &gt; 0 || ret == -1;
453
+ <a name="l00436"></a>00436 <span class="keywordflow">if</span> (!done) {
454
+ <a name="l00437"></a>00437 InterruptableCalls::usleep(100000);
455
+ <a name="l00438"></a>00438 }
456
+ <a name="l00439"></a>00439 }
457
+ <a name="l00440"></a>00440 <span class="keywordflow">if</span> (done) {
458
+ <a name="l00441"></a>00441 P_TRACE(2, <span class="stringliteral">"ApplicationPoolServerExecutable exited."</span>);
459
+ <a name="l00442"></a>00442 } <span class="keywordflow">else</span> {
460
+ <a name="l00443"></a>00443 P_DEBUG(<span class="stringliteral">"ApplicationPoolServerExecutable not exited in time. Killing it..."</span>);
461
+ <a name="l00444"></a>00444 InterruptableCalls::kill(serverPid, SIGTERM);
462
+ <a name="l00445"></a>00445 InterruptableCalls::waitpid(serverPid, NULL, 0);
463
+ <a name="l00446"></a>00446 }
464
+ <a name="l00447"></a>00447
465
+ <a name="l00448"></a>00448 serverSocket = -1;
466
+ <a name="l00449"></a>00449 serverPid = 0;
467
+ <a name="l00450"></a>00450 }
468
+ <a name="l00451"></a>00451 <span class="comment"></span>
469
+ <a name="l00452"></a>00452 <span class="comment"> /**</span>
470
+ <a name="l00453"></a>00453 <span class="comment"> * Start an ApplicationPool server process. If there's already one running,</span>
471
+ <a name="l00454"></a>00454 <span class="comment"> * then the currently running one will be shutdown.</span>
472
+ <a name="l00455"></a>00455 <span class="comment"> *</span>
473
+ <a name="l00456"></a>00456 <span class="comment"> * @pre System call interruption is disabled.</span>
474
+ <a name="l00457"></a>00457 <span class="comment"> * @post serverSocket != -1 &amp;&amp; serverPid != 0</span>
475
+ <a name="l00458"></a>00458 <span class="comment"> * @throw SystemException Something went wrong.</span>
476
+ <a name="l00459"></a>00459 <span class="comment"> */</span>
477
+ <a name="l00460"></a>00460 <span class="keywordtype">void</span> restartServer() {
478
+ <a name="l00461"></a>00461 <span class="keywordtype">int</span> fds[2];
479
+ <a name="l00462"></a>00462 pid_t pid;
480
+ <a name="l00463"></a>00463
481
+ <a name="l00464"></a>00464 <span class="keywordflow">if</span> (serverPid != 0) {
482
+ <a name="l00465"></a>00465 shutdownServer();
483
+ <a name="l00466"></a>00466 }
484
+ <a name="l00467"></a>00467
485
+ <a name="l00468"></a>00468 <span class="keywordflow">if</span> (InterruptableCalls::socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) {
486
+ <a name="l00469"></a>00469 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot create a Unix socket pair"</span>, errno);
487
+ <a name="l00470"></a>00470 }
488
+ <a name="l00471"></a>00471
489
+ <a name="l00472"></a>00472 createStatusReportFIFO();
490
+ <a name="l00473"></a>00473
491
+ <a name="l00474"></a>00474 pid = InterruptableCalls::fork();
492
+ <a name="l00475"></a>00475 <span class="keywordflow">if</span> (pid == 0) { <span class="comment">// Child process.</span>
493
+ <a name="l00476"></a>00476 dup2(fds[0], SERVER_SOCKET_FD);
494
+ <a name="l00477"></a>00477
495
+ <a name="l00478"></a>00478 <span class="comment">// Close all unnecessary file descriptors</span>
496
+ <a name="l00479"></a>00479 <span class="keywordflow">for</span> (<span class="keywordtype">long</span> i = sysconf(_SC_OPEN_MAX) - 1; i &gt; SERVER_SOCKET_FD; i--) {
497
+ <a name="l00480"></a>00480 close(i);
498
+ <a name="l00481"></a>00481 }
499
+ <a name="l00482"></a>00482
500
+ <a name="l00483"></a>00483 execlp(
501
+ <a name="l00484"></a>00484 #<span class="keywordflow">if</span> 0
502
+ <a name="l00485"></a>00485 <span class="stringliteral">"valgrind"</span>,
503
+ <a name="l00486"></a>00486 <span class="stringliteral">"valgrind"</span>,
504
+ <a name="l00487"></a>00487 #<span class="keywordflow">else</span>
505
+ <a name="l00488"></a>00488 m_serverExecutable.c_str(),
506
+ <a name="l00489"></a>00489 <span class="preprocessor"> #endif</span>
507
+ <a name="l00490"></a>00490 <span class="preprocessor"></span> m_serverExecutable.c_str(),
508
+ <a name="l00491"></a>00491 <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(Passenger::getLogLevel()).c_str(),
509
+ <a name="l00492"></a>00492 m_spawnServerCommand.c_str(),
510
+ <a name="l00493"></a>00493 m_logFile.c_str(),
511
+ <a name="l00494"></a>00494 m_rubyCommand.c_str(),
512
+ <a name="l00495"></a>00495 m_user.c_str(),
513
+ <a name="l00496"></a>00496 statusReportFIFO.c_str(),
514
+ <a name="l00497"></a>00497 NULL);
515
+ <a name="l00498"></a>00498 <span class="keywordtype">int</span> e = errno;
516
+ <a name="l00499"></a>00499 fprintf(stderr, <span class="stringliteral">"*** Passenger ERROR: Cannot execute %s: %s (%d)\n"</span>,
517
+ <a name="l00500"></a>00500 m_serverExecutable.c_str(), strerror(e), e);
518
+ <a name="l00501"></a>00501 fflush(stderr);
519
+ <a name="l00502"></a>00502 _exit(1);
520
+ <a name="l00503"></a>00503 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pid == -1) { <span class="comment">// Error.</span>
521
+ <a name="l00504"></a>00504 InterruptableCalls::close(fds[0]);
522
+ <a name="l00505"></a>00505 InterruptableCalls::close(fds[1]);
523
+ <a name="l00506"></a>00506 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot create a new process"</span>, errno);
524
+ <a name="l00507"></a>00507 } <span class="keywordflow">else</span> { <span class="comment">// Parent process.</span>
525
+ <a name="l00508"></a>00508 InterruptableCalls::close(fds[0]);
526
+ <a name="l00509"></a>00509 serverSocket = fds[1];
527
+ <a name="l00510"></a>00510 serverPid = pid;
528
+ <a name="l00511"></a>00511 }
529
+ <a name="l00512"></a>00512 }
530
+ <a name="l00513"></a>00513
531
+ <a name="l00514"></a>00514 <span class="keywordtype">void</span> createStatusReportFIFO() {
532
+ <a name="l00515"></a>00515 <span class="keywordtype">char</span> filename[PATH_MAX];
533
+ <a name="l00516"></a>00516 <span class="keywordtype">int</span> ret;
534
+ <a name="l00517"></a>00517
535
+ <a name="l00518"></a>00518 snprintf(filename, <span class="keyword">sizeof</span>(filename), <span class="stringliteral">"/tmp/passenger_status.%d.fifo"</span>,
536
+ <a name="l00519"></a>00519 getpid());
537
+ <a name="l00520"></a>00520 filename[PATH_MAX - 1] = <span class="charliteral">'\0'</span>;
538
+ <a name="l00521"></a>00521 <span class="keywordflow">do</span> {
539
+ <a name="l00522"></a>00522 ret = mkfifo(filename, S_IRUSR | S_IWUSR);
540
+ <a name="l00523"></a>00523 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; errno == EINTR);
541
+ <a name="l00524"></a>00524 <span class="keywordflow">if</span> (ret == -1 &amp;&amp; errno != EEXIST) {
542
+ <a name="l00525"></a>00525 <span class="keywordtype">int</span> e = errno;
543
+ <a name="l00526"></a>00526 P_WARN(<span class="stringliteral">"*** WARNING: Could not create FIFO '"</span> &lt;&lt; filename &lt;&lt;
544
+ <a name="l00527"></a>00527 <span class="stringliteral">"': "</span> &lt;&lt; strerror(e) &lt;&lt; <span class="stringliteral">" ("</span> &lt;&lt; e &lt;&lt; <span class="stringliteral">")"</span> &lt;&lt; endl &lt;&lt;
545
+ <a name="l00528"></a>00528 <span class="stringliteral">"Disabling Passenger ApplicationPool status reporting."</span>);
546
+ <a name="l00529"></a>00529 statusReportFIFO = <span class="stringliteral">""</span>;
547
+ <a name="l00530"></a>00530 } <span class="keywordflow">else</span> {
548
+ <a name="l00531"></a>00531 statusReportFIFO = filename;
549
+ <a name="l00532"></a>00532 }
550
+ <a name="l00533"></a>00533 }
551
+ <a name="l00534"></a>00534
552
+ <a name="l00535"></a>00535 <span class="keyword">public</span>:<span class="comment"></span>
553
+ <a name="l00536"></a>00536 <span class="comment"> /**</span>
554
+ <a name="l00537"></a>00537 <span class="comment"> * Create a new ApplicationPoolServer object.</span>
555
+ <a name="l00538"></a>00538 <span class="comment"> *</span>
556
+ <a name="l00539"></a>00539 <span class="comment"> * @param serverExecutable The filename of the ApplicationPool server</span>
557
+ <a name="l00540"></a>00540 <span class="comment"> * executable to use.</span>
558
+ <a name="l00541"></a>00541 <span class="comment"> * @param spawnServerCommand The filename of the spawn server to use.</span>
559
+ <a name="l00542"></a>00542 <span class="comment"> * @param logFile Specify a log file that the spawn server should use.</span>
560
+ <a name="l00543"></a>00543 <span class="comment"> * Messages on its standard output and standard error channels</span>
561
+ <a name="l00544"></a>00544 <span class="comment"> * will be written to this log file. If an empty string is</span>
562
+ <a name="l00545"></a>00545 <span class="comment"> * specified, no log file will be used, and the spawn server</span>
563
+ <a name="l00546"></a>00546 <span class="comment"> * will use the same standard output/error channels as the</span>
564
+ <a name="l00547"></a>00547 <span class="comment"> * current process.</span>
565
+ <a name="l00548"></a>00548 <span class="comment"> * @param rubyCommand The Ruby interpreter's command.</span>
566
+ <a name="l00549"></a>00549 <span class="comment"> * @param user The user that the spawn manager should run as. This</span>
567
+ <a name="l00550"></a>00550 <span class="comment"> * parameter only has effect if the current process is</span>
568
+ <a name="l00551"></a>00551 <span class="comment"> * running as root. If the empty string is given, or if</span>
569
+ <a name="l00552"></a>00552 <span class="comment"> * the &lt;tt&gt;user&lt;/tt&gt; is not a valid username, then</span>
570
+ <a name="l00553"></a>00553 <span class="comment"> * the spawn manager will be run as the current user.</span>
571
+ <a name="l00554"></a>00554 <span class="comment"> * @throws SystemException An error occured while trying to setup the spawn server</span>
572
+ <a name="l00555"></a>00555 <span class="comment"> * or the server socket.</span>
573
+ <a name="l00556"></a>00556 <span class="comment"> * @throws IOException The specified log file could not be opened.</span>
574
+ <a name="l00557"></a>00557 <span class="comment"> */</span>
575
+ <a name="l00558"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html#2203db62a022579d569ceddff8ef6ca9">00558</a> <a class="code" href="classPassenger_1_1ApplicationPoolServer.html#2203db62a022579d569ceddff8ef6ca9" title="Create a new ApplicationPoolServer object.">ApplicationPoolServer</a>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;serverExecutable,
576
+ <a name="l00559"></a>00559 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;spawnServerCommand,
577
+ <a name="l00560"></a>00560 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;logFile = <span class="stringliteral">""</span>,
578
+ <a name="l00561"></a>00561 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;rubyCommand = <span class="stringliteral">"ruby"</span>,
579
+ <a name="l00562"></a>00562 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;user = <span class="stringliteral">""</span>)
580
+ <a name="l00563"></a>00563 : m_serverExecutable(serverExecutable),
581
+ <a name="l00564"></a>00564 m_spawnServerCommand(spawnServerCommand),
582
+ <a name="l00565"></a>00565 m_logFile(logFile),
583
+ <a name="l00566"></a>00566 m_rubyCommand(rubyCommand),
584
+ <a name="l00567"></a>00567 m_user(user) {
585
+ <a name="l00568"></a>00568 serverSocket = -1;
586
+ <a name="l00569"></a>00569 serverPid = 0;
587
+ <a name="l00570"></a>00570 <a class="code" href="classboost_1_1this__thread_1_1disable__syscall__interruption.html" title="Create this struct on the stack to temporarily disable system call interruption,...">this_thread::disable_syscall_interruption</a> dsi;
588
+ <a name="l00571"></a>00571 restartServer();
589
+ <a name="l00572"></a>00572 }
590
+ <a name="l00573"></a>00573
591
+ <a name="l00574"></a>00574 ~<a class="code" href="classPassenger_1_1ApplicationPoolServer.html" title="Multi-process usage support for ApplicationPool.">ApplicationPoolServer</a>() {
592
+ <a name="l00575"></a>00575 <span class="keywordflow">if</span> (serverSocket != -1) {
593
+ <a name="l00576"></a>00576 <a class="code" href="classboost_1_1this__thread_1_1disable__syscall__interruption.html" title="Create this struct on the stack to temporarily disable system call interruption,...">this_thread::disable_syscall_interruption</a> dsi;
594
+ <a name="l00577"></a>00577 shutdownServer();
595
+ <a name="l00578"></a>00578 }
596
+ <a name="l00579"></a>00579 }
597
+ <a name="l00580"></a>00580 <span class="comment"></span>
598
+ <a name="l00581"></a>00581 <span class="comment"> /**</span>
599
+ <a name="l00582"></a>00582 <span class="comment"> * Connects to the server and returns a usable ApplicationPool object.</span>
600
+ <a name="l00583"></a>00583 <span class="comment"> * All cache/pool data of this ApplicationPool is actually stored on</span>
601
+ <a name="l00584"></a>00584 <span class="comment"> * the server and shared with other clients, but that is totally</span>
602
+ <a name="l00585"></a>00585 <span class="comment"> * transparent to the user of the ApplicationPool object.</span>
603
+ <a name="l00586"></a>00586 <span class="comment"> *</span>
604
+ <a name="l00587"></a>00587 <span class="comment"> * @note</span>
605
+ <a name="l00588"></a>00588 <span class="comment"> * All methods of the returned ApplicationPool object may throw</span>
606
+ <a name="l00589"></a>00589 <span class="comment"> * SystemException, IOException or boost::thread_interrupted.</span>
607
+ <a name="l00590"></a>00590 <span class="comment"> *</span>
608
+ <a name="l00591"></a>00591 <span class="comment"> * @warning</span>
609
+ <a name="l00592"></a>00592 <span class="comment"> * One may only use the returned ApplicationPool object for handling</span>
610
+ <a name="l00593"></a>00593 <span class="comment"> * one session at a time. For example, don't do stuff like this:</span>
611
+ <a name="l00594"></a>00594 <span class="comment"> * @code</span>
612
+ <a name="l00595"></a>00595 <span class="comment"> * ApplicationPoolPtr pool = server.connect();</span>
613
+ <a name="l00596"></a>00596 <span class="comment"> * Application::SessionPtr session1 = pool-&gt;get(...);</span>
614
+ <a name="l00597"></a>00597 <span class="comment"> * Application::SessionPtr session2 = pool-&gt;get(...);</span>
615
+ <a name="l00598"></a>00598 <span class="comment"> * @endcode</span>
616
+ <a name="l00599"></a>00599 <span class="comment"> * Otherwise, a deadlock can occur under certain circumstances.</span>
617
+ <a name="l00600"></a>00600 <span class="comment"> * @warning</span>
618
+ <a name="l00601"></a>00601 <span class="comment"> * Instead, one should call connect() multiple times:</span>
619
+ <a name="l00602"></a>00602 <span class="comment"> * @code</span>
620
+ <a name="l00603"></a>00603 <span class="comment"> * ApplicationPoolPtr pool1 = server.connect();</span>
621
+ <a name="l00604"></a>00604 <span class="comment"> * Application::SessionPtr session1 = pool1-&gt;get(...);</span>
622
+ <a name="l00605"></a>00605 <span class="comment"> * </span>
623
+ <a name="l00606"></a>00606 <span class="comment"> * ApplicationPoolPtr pool2 = server.connect();</span>
624
+ <a name="l00607"></a>00607 <span class="comment"> * Application::SessionPtr session2 = pool2-&gt;get(...);</span>
625
+ <a name="l00608"></a>00608 <span class="comment"> * @endcode</span>
626
+ <a name="l00609"></a>00609 <span class="comment"> *</span>
627
+ <a name="l00610"></a>00610 <span class="comment"> * @throws SystemException Something went wrong.</span>
628
+ <a name="l00611"></a>00611 <span class="comment"> * @throws IOException Something went wrong.</span>
629
+ <a name="l00612"></a>00612 <span class="comment"> */</span>
630
+ <a name="l00613"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html#18f77057cc28e7924a8f4d1397aa0468">00613</a> ApplicationPoolPtr <a class="code" href="classPassenger_1_1ApplicationPoolServer.html#18f77057cc28e7924a8f4d1397aa0468" title="Connects to the server and returns a usable ApplicationPool object.">connect</a>() {
631
+ <a name="l00614"></a>00614 <span class="keywordflow">try</span> {
632
+ <a name="l00615"></a>00615 <a class="code" href="classboost_1_1this__thread_1_1disable__syscall__interruption.html" title="Create this struct on the stack to temporarily disable system call interruption,...">this_thread::disable_syscall_interruption</a> dsi;
633
+ <a name="l00616"></a>00616 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(serverSocket);
634
+ <a name="l00617"></a>00617 <span class="keywordtype">int</span> clientConnection;
635
+ <a name="l00618"></a>00618
636
+ <a name="l00619"></a>00619 <span class="comment">// Write some random data to wake up the server.</span>
637
+ <a name="l00620"></a>00620 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#069314e4c7e1fe8c8ab36e16d2cc5fef" title="Send a block of data over the underlying file descriptor.">writeRaw</a>(<span class="stringliteral">"x"</span>, 1);
638
+ <a name="l00621"></a>00621
639
+ <a name="l00622"></a>00622 clientConnection = channel.<a class="code" href="classPassenger_1_1MessageChannel.html#1561b7e4a0f4d39ea431f456e5655488" title="Receive a file descriptor, which had been passed over the underlying file descriptor...">readFileDescriptor</a>();
640
+ <a name="l00623"></a>00623 <span class="keywordflow">return</span> <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(<span class="keyword">new</span> Client(clientConnection));
641
+ <a name="l00624"></a>00624 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a> &amp;e) {
642
+ <a name="l00625"></a>00625 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Could not connect to the ApplicationPool server"</span>, e.<a class="code" href="classPassenger_1_1SystemException.html#ee7a6672bf79b72a4c3ee70c57d6a47c" title="The value of errno at the time the error occured.">code</a>());
643
+ <a name="l00626"></a>00626 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a> &amp;e) {
644
+ <a name="l00627"></a>00627 <span class="keywordtype">string</span> message(<span class="stringliteral">"Could not connect to the ApplicationPool server: "</span>);
645
+ <a name="l00628"></a>00628 message.append(e.<a class="code" href="classPassenger_1_1IOException.html#1b65d0fdb9bc5136f5b7df759c14768a">what</a>());
646
+ <a name="l00629"></a>00629 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(message);
647
+ <a name="l00630"></a>00630 }
648
+ <a name="l00631"></a>00631 }
649
+ <a name="l00632"></a>00632 <span class="comment"></span>
650
+ <a name="l00633"></a>00633 <span class="comment"> /**</span>
651
+ <a name="l00634"></a>00634 <span class="comment"> * Detach the server, thereby telling it that we don't want to connect</span>
652
+ <a name="l00635"></a>00635 <span class="comment"> * to it anymore. This frees up some resources in the current process,</span>
653
+ <a name="l00636"></a>00636 <span class="comment"> * such as file descriptors.</span>
654
+ <a name="l00637"></a>00637 <span class="comment"> *</span>
655
+ <a name="l00638"></a>00638 <span class="comment"> * This method is particularily useful to Apache worker processes that</span>
656
+ <a name="l00639"></a>00639 <span class="comment"> * have just established a connection with the ApplicationPool server.</span>
657
+ <a name="l00640"></a>00640 <span class="comment"> * Any sessions that are opened prior to calling detach(), will keep</span>
658
+ <a name="l00641"></a>00641 <span class="comment"> * working even after a detach().</span>
659
+ <a name="l00642"></a>00642 <span class="comment"> *</span>
660
+ <a name="l00643"></a>00643 <span class="comment"> * This method may only be called once. The ApplicationPoolServer object</span>
661
+ <a name="l00644"></a>00644 <span class="comment"> * will become unusable once detach() has been called, so call connect()</span>
662
+ <a name="l00645"></a>00645 <span class="comment"> * before calling detach().</span>
663
+ <a name="l00646"></a>00646 <span class="comment"> */</span>
664
+ <a name="l00647"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html#b13957e32ae8ca36ba85f2e6ffefd5ce">00647</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1ApplicationPoolServer.html#b13957e32ae8ca36ba85f2e6ffefd5ce" title="Detach the server, thereby telling it that we don&amp;#39;t want to connect to it anymore...">detach</a>() {
665
+ <a name="l00648"></a>00648 <span class="keywordtype">int</span> ret;
666
+ <a name="l00649"></a>00649 <span class="keywordflow">do</span> {
667
+ <a name="l00650"></a>00650 ret = close(serverSocket);
668
+ <a name="l00651"></a>00651 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; errno == EINTR);
669
+ <a name="l00652"></a>00652 serverSocket = -1;
670
+ <a name="l00653"></a>00653 }
671
+ <a name="l00654"></a>00654 };
672
+ <a name="l00655"></a>00655
673
+ <a name="l00656"></a>00656 <span class="keyword">typedef</span> shared_ptr&lt;ApplicationPoolServer&gt; ApplicationPoolServerPtr;
674
+ <a name="l00657"></a>00657
675
+ <a name="l00658"></a>00658 } <span class="comment">// namespace Passenger</span>
676
+ <a name="l00659"></a>00659
677
+ <a name="l00660"></a>00660 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_APPLICATION_POOL_SERVER_H_ */</span>
678
+ </pre></div></div>
679
+ <hr size="1"><address style="text-align: right;"><small>Generated on Mon Dec 1 14:27:22 2008 for Passenger by&nbsp;
680
+ <a href="http://www.doxygen.org/index.html">
681
+ <img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.5 </small></address>
682
+ </body>
683
+ </html>