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.
- data/Rakefile +8 -5
- data/bin/passenger-install-apache2-module +6 -1
- data/doc/ApplicationPool algorithm.txt +23 -5
- data/doc/Architectural overview.html +778 -0
- data/doc/Security of user switching support.html +1 -1
- data/doc/Users guide.html +113 -31
- data/doc/Users guide.txt +104 -10
- data/doc/cxxapi/ApplicationPoolServer_8h-source.html +683 -0
- data/doc/cxxapi/ApplicationPool_8h-source.html +224 -0
- data/doc/cxxapi/Application_8h-source.html +448 -0
- data/doc/cxxapi/Bucket_8h-source.html +61 -0
- data/doc/cxxapi/Configuration_8h-source.html +195 -0
- data/doc/cxxapi/DummySpawnManager_8h-source.html +126 -0
- data/doc/cxxapi/Exceptions_8h-source.html +244 -0
- data/doc/cxxapi/Hooks_8h-source.html +63 -0
- data/doc/cxxapi/Logging_8h-source.html +136 -0
- data/doc/cxxapi/MessageChannel_8h-source.html +524 -0
- data/doc/cxxapi/SpawnManager_8h-source.html +593 -0
- data/doc/cxxapi/StandardApplicationPool_8h-source.html +732 -0
- data/doc/cxxapi/System_8h-source.html +251 -0
- data/doc/cxxapi/Utils_8h-source.html +283 -0
- data/doc/cxxapi/annotated.html +59 -0
- data/doc/cxxapi/classClient-members.html +35 -0
- data/doc/cxxapi/classClient.html +117 -0
- data/doc/cxxapi/classDirectoryMapper-members.html +38 -0
- data/doc/cxxapi/classDirectoryMapper.html +203 -0
- data/doc/cxxapi/classHooks-members.html +33 -0
- data/doc/cxxapi/classHooks.html +43 -0
- data/doc/cxxapi/classPassenger_1_1Application-members.html +38 -0
- data/doc/cxxapi/classPassenger_1_1Application.html +229 -0
- data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +41 -0
- data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +359 -0
- data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +36 -0
- data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +225 -0
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.map +1 -0
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.md5 +1 -0
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +43 -0
- data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +329 -0
- data/doc/cxxapi/classPassenger_1_1BusyException-members.html +33 -0
- data/doc/cxxapi/classPassenger_1_1BusyException.html +47 -0
- data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +33 -0
- data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +44 -0
- data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +33 -0
- data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +51 -0
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +33 -0
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +51 -0
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.map +1 -0
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.md5 +1 -0
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +38 -0
- data/doc/cxxapi/classPassenger_1_1FileSystemException.html +61 -0
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.map +1 -0
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.md5 +1 -0
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1IOException-members.html +33 -0
- data/doc/cxxapi/classPassenger_1_1IOException.html +54 -0
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.map +1 -0
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.md5 +1 -0
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +47 -0
- data/doc/cxxapi/classPassenger_1_1MessageChannel.html +591 -0
- data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +35 -0
- data/doc/cxxapi/classPassenger_1_1SpawnException.html +77 -0
- data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +37 -0
- data/doc/cxxapi/classPassenger_1_1SpawnManager.html +255 -0
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +43 -0
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +400 -0
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.map +1 -0
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.md5 +1 -0
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1SystemException-members.html +37 -0
- data/doc/cxxapi/classPassenger_1_1SystemException.html +154 -0
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.map +1 -0
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.md5 +1 -0
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1TempFile-members.html +36 -0
- data/doc/cxxapi/classPassenger_1_1TempFile.html +128 -0
- data/doc/cxxapi/classPassenger_1_1Thread-members.html +35 -0
- data/doc/cxxapi/classPassenger_1_1Thread.html +100 -0
- data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption-members.html +33 -0
- data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption.html +46 -0
- data/doc/cxxapi/classboost_1_1this__thread_1_1enable__syscall__interruption-members.html +33 -0
- data/doc/cxxapi/classboost_1_1this__thread_1_1enable__syscall__interruption.html +44 -0
- data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption-members.html +33 -0
- data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption.html +44 -0
- data/doc/cxxapi/definitions_8h-source.html +28 -0
- data/doc/cxxapi/doxygen.css +433 -0
- data/doc/cxxapi/doxygen.png +0 -0
- data/doc/cxxapi/files.html +42 -0
- data/doc/cxxapi/ftv2blank.png +0 -0
- data/doc/cxxapi/ftv2doc.png +0 -0
- data/doc/cxxapi/ftv2folderclosed.png +0 -0
- data/doc/cxxapi/ftv2folderopen.png +0 -0
- data/doc/cxxapi/ftv2lastnode.png +0 -0
- data/doc/cxxapi/ftv2link.png +0 -0
- data/doc/cxxapi/ftv2mlastnode.png +0 -0
- data/doc/cxxapi/ftv2mnode.png +0 -0
- data/doc/cxxapi/ftv2node.png +0 -0
- data/doc/cxxapi/ftv2plastnode.png +0 -0
- data/doc/cxxapi/ftv2pnode.png +0 -0
- data/doc/cxxapi/ftv2vertline.png +0 -0
- data/doc/cxxapi/functions.html +215 -0
- data/doc/cxxapi/functions_func.html +210 -0
- data/doc/cxxapi/functions_type.html +46 -0
- data/doc/cxxapi/functions_vars.html +48 -0
- data/doc/cxxapi/graph_legend.dot +22 -0
- data/doc/cxxapi/graph_legend.html +87 -0
- data/doc/cxxapi/graph_legend.png +0 -0
- data/doc/cxxapi/group__Configuration.html +236 -0
- data/doc/cxxapi/group__Configuration.png +0 -0
- data/doc/cxxapi/group__Core.html +51 -0
- data/doc/cxxapi/group__Core.png +0 -0
- data/doc/cxxapi/group__Exceptions.html +43 -0
- data/doc/cxxapi/group__Hooks.html +46 -0
- data/doc/cxxapi/group__Hooks.png +0 -0
- data/doc/cxxapi/group__Support.html +406 -0
- data/doc/cxxapi/hierarchy.html +67 -0
- data/doc/cxxapi/index.html +11 -0
- data/doc/cxxapi/inherit__graph__0.map +1 -0
- data/doc/cxxapi/inherit__graph__0.md5 +1 -0
- data/doc/cxxapi/inherit__graph__0.png +0 -0
- data/doc/cxxapi/inherit__graph__1.map +1 -0
- data/doc/cxxapi/inherit__graph__1.md5 +1 -0
- data/doc/cxxapi/inherit__graph__1.png +0 -0
- data/doc/cxxapi/inherit__graph__10.map +1 -0
- data/doc/cxxapi/inherit__graph__10.md5 +1 -0
- data/doc/cxxapi/inherit__graph__10.png +0 -0
- data/doc/cxxapi/inherit__graph__11.map +1 -0
- data/doc/cxxapi/inherit__graph__11.md5 +1 -0
- data/doc/cxxapi/inherit__graph__11.png +0 -0
- data/doc/cxxapi/inherit__graph__12.map +1 -0
- data/doc/cxxapi/inherit__graph__12.md5 +1 -0
- data/doc/cxxapi/inherit__graph__12.png +0 -0
- data/doc/cxxapi/inherit__graph__13.map +1 -0
- data/doc/cxxapi/inherit__graph__13.md5 +1 -0
- data/doc/cxxapi/inherit__graph__13.png +0 -0
- data/doc/cxxapi/inherit__graph__14.map +2 -0
- data/doc/cxxapi/inherit__graph__14.md5 +1 -0
- data/doc/cxxapi/inherit__graph__14.png +0 -0
- data/doc/cxxapi/inherit__graph__15.map +1 -0
- data/doc/cxxapi/inherit__graph__15.md5 +1 -0
- data/doc/cxxapi/inherit__graph__15.png +0 -0
- data/doc/cxxapi/inherit__graph__16.map +1 -0
- data/doc/cxxapi/inherit__graph__16.md5 +1 -0
- data/doc/cxxapi/inherit__graph__16.png +0 -0
- data/doc/cxxapi/inherit__graph__17.map +1 -0
- data/doc/cxxapi/inherit__graph__17.md5 +1 -0
- data/doc/cxxapi/inherit__graph__17.png +0 -0
- data/doc/cxxapi/inherit__graph__18.map +1 -0
- data/doc/cxxapi/inherit__graph__18.md5 +1 -0
- data/doc/cxxapi/inherit__graph__18.png +0 -0
- data/doc/cxxapi/inherit__graph__19.map +2 -0
- data/doc/cxxapi/inherit__graph__19.md5 +1 -0
- data/doc/cxxapi/inherit__graph__19.png +0 -0
- data/doc/cxxapi/inherit__graph__2.map +1 -0
- data/doc/cxxapi/inherit__graph__2.md5 +1 -0
- data/doc/cxxapi/inherit__graph__2.png +0 -0
- data/doc/cxxapi/inherit__graph__20.map +1 -0
- data/doc/cxxapi/inherit__graph__20.md5 +1 -0
- data/doc/cxxapi/inherit__graph__20.png +0 -0
- data/doc/cxxapi/inherit__graph__21.map +1 -0
- data/doc/cxxapi/inherit__graph__21.md5 +1 -0
- data/doc/cxxapi/inherit__graph__21.png +0 -0
- data/doc/cxxapi/inherit__graph__3.map +1 -0
- data/doc/cxxapi/inherit__graph__3.md5 +1 -0
- data/doc/cxxapi/inherit__graph__3.png +0 -0
- data/doc/cxxapi/inherit__graph__4.map +1 -0
- data/doc/cxxapi/inherit__graph__4.md5 +1 -0
- data/doc/cxxapi/inherit__graph__4.png +0 -0
- data/doc/cxxapi/inherit__graph__5.map +1 -0
- data/doc/cxxapi/inherit__graph__5.md5 +1 -0
- data/doc/cxxapi/inherit__graph__5.png +0 -0
- data/doc/cxxapi/inherit__graph__6.map +1 -0
- data/doc/cxxapi/inherit__graph__6.md5 +1 -0
- data/doc/cxxapi/inherit__graph__6.png +0 -0
- data/doc/cxxapi/inherit__graph__7.map +1 -0
- data/doc/cxxapi/inherit__graph__7.md5 +1 -0
- data/doc/cxxapi/inherit__graph__7.png +0 -0
- data/doc/cxxapi/inherit__graph__8.map +1 -0
- data/doc/cxxapi/inherit__graph__8.md5 +1 -0
- data/doc/cxxapi/inherit__graph__8.png +0 -0
- data/doc/cxxapi/inherit__graph__9.map +2 -0
- data/doc/cxxapi/inherit__graph__9.md5 +1 -0
- data/doc/cxxapi/inherit__graph__9.png +0 -0
- data/doc/cxxapi/inherits.html +102 -0
- data/doc/cxxapi/main.html +27 -0
- data/doc/cxxapi/modules.html +34 -0
- data/doc/cxxapi/namespacePassenger.html +208 -0
- data/doc/cxxapi/namespacePassenger_1_1InterruptableCalls.html +43 -0
- data/doc/cxxapi/namespacemembers.html +70 -0
- data/doc/cxxapi/namespacemembers_func.html +66 -0
- data/doc/cxxapi/namespacemembers_type.html +46 -0
- data/doc/cxxapi/namespaces.html +35 -0
- data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +33 -0
- data/doc/cxxapi/structPassenger_1_1AnythingToString.html +49 -0
- data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +33 -0
- data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +49 -0
- data/doc/cxxapi/tab_b.gif +0 -0
- data/doc/cxxapi/tab_l.gif +0 -0
- data/doc/cxxapi/tab_r.gif +0 -0
- data/doc/cxxapi/tabs.css +102 -0
- data/doc/cxxapi/tree.html +167 -0
- data/doc/rdoc/classes/ConditionVariable.html +160 -0
- data/doc/rdoc/classes/Exception.html +120 -0
- data/doc/rdoc/classes/GC.html +113 -0
- data/doc/rdoc/classes/IO.html +150 -0
- data/doc/rdoc/classes/Passenger.html +136 -0
- data/doc/rdoc/classes/Passenger/AbstractRequestHandler.html +402 -0
- data/doc/rdoc/classes/Passenger/AbstractServer.html +649 -0
- data/doc/rdoc/classes/Passenger/AbstractServer/ServerAlreadyStarted.html +97 -0
- data/doc/rdoc/classes/Passenger/AbstractServer/ServerError.html +96 -0
- data/doc/rdoc/classes/Passenger/AbstractServer/ServerNotStarted.html +97 -0
- data/doc/rdoc/classes/Passenger/AbstractServer/UnknownMessage.html +96 -0
- data/doc/rdoc/classes/Passenger/AppInitError.html +137 -0
- data/doc/rdoc/classes/Passenger/Application.html +298 -0
- data/doc/rdoc/classes/Passenger/ConsoleTextTemplate.html +172 -0
- data/doc/rdoc/classes/Passenger/FrameworkInitError.html +143 -0
- data/doc/rdoc/classes/Passenger/HTMLTemplate.html +175 -0
- data/doc/rdoc/classes/Passenger/InitializationError.html +141 -0
- data/doc/rdoc/classes/Passenger/MessageChannel.html +488 -0
- data/doc/rdoc/classes/Passenger/NativeSupport.html +320 -0
- data/doc/rdoc/classes/Passenger/SpawnManager.html +375 -0
- data/doc/rdoc/classes/Passenger/UnknownError.html +125 -0
- data/doc/rdoc/classes/Passenger/Utils.html +578 -0
- data/doc/rdoc/classes/Passenger/VersionNotFound.html +140 -0
- data/doc/rdoc/classes/PlatformInfo.html +302 -0
- data/doc/rdoc/classes/RakeExtensions.html +197 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/DEVELOPERS_TXT.html +230 -0
- data/doc/rdoc/files/README.html +150 -0
- data/doc/rdoc/files/ext/passenger/native_support_c.html +92 -0
- data/doc/rdoc/files/lib/passenger/abstract_request_handler_rb.html +126 -0
- data/doc/rdoc/files/lib/passenger/abstract_server_rb.html +127 -0
- data/doc/rdoc/files/lib/passenger/application_rb.html +123 -0
- data/doc/rdoc/files/lib/passenger/console_text_template_rb.html +122 -0
- data/doc/rdoc/files/lib/passenger/constants_rb.html +114 -0
- data/doc/rdoc/files/lib/passenger/dependencies_rb.html +130 -0
- data/doc/rdoc/files/lib/passenger/exceptions_rb.html +118 -0
- data/doc/rdoc/files/lib/passenger/html_template_rb.html +122 -0
- data/doc/rdoc/files/lib/passenger/message_channel_rb.html +118 -0
- data/doc/rdoc/files/lib/passenger/platform_info_rb.html +122 -0
- data/doc/rdoc/files/lib/passenger/simple_benchmarking_rb.html +118 -0
- data/doc/rdoc/files/lib/passenger/spawn_manager_rb.html +139 -0
- data/doc/rdoc/files/lib/passenger/utils_rb.html +130 -0
- data/doc/rdoc/files/lib/rake/extensions_rb.html +122 -0
- data/doc/rdoc/fr_class_index.html +71 -0
- data/doc/rdoc/fr_file_index.html +63 -0
- data/doc/rdoc/fr_method_index.html +120 -0
- data/doc/rdoc/index.html +26 -0
- data/doc/rdoc/rdoc-style.css +187 -0
- data/ext/apache2/ApplicationPool.h +12 -0
- data/ext/apache2/ApplicationPoolServer.h +6 -0
- data/ext/apache2/ApplicationPoolServerExecutable.cpp +6 -0
- data/ext/apache2/Bucket.cpp +63 -69
- data/ext/apache2/Bucket.h +2 -0
- data/ext/apache2/Configuration.cpp +24 -0
- data/ext/apache2/Configuration.h +16 -1
- data/ext/apache2/Hooks.cpp +5 -3
- data/ext/apache2/StandardApplicationPool.h +30 -11
- data/lib/passenger/abstract_request_handler.rb +3 -0
- data/lib/passenger/abstract_server.rb +3 -3
- data/lib/passenger/application.rb +4 -2
- data/lib/passenger/dependencies.rb +10 -1
- data/lib/passenger/platform_info.rb +40 -1
- data/lib/passenger/rack/request_handler.rb +4 -2
- data/lib/passenger/railz/application_spawner.rb +7 -1
- data/lib/passenger/utils.rb +6 -8
- data/lib/rake/gempackagetask.rb +0 -6
- data/lib/rake/rdoctask.rb +84 -23
- data/test/ApplicationPoolTest.cpp +36 -0
- data/test/ruby/rails/minimal_spawner_spec.rb +8 -0
- data/test/ruby/utils_spec.rb +33 -0
- data/test/stub/rails_apps/foobar/config/environments/production.rb +0 -1
- metadata +262 -5
data/doc/Users guide.html
CHANGED
@@ -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 => File.join(root_dir, 'views'),
|
1048
|
+
:app_file => File.join(root_dir, 'app.rb'),
|
1044
1049
|
:run => false,
|
1045
|
-
:env => ENV['RACK_ENV']
|
1050
|
+
:env => 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="
|
1102
|
+
<h3 id="PassengerUseGlobalQueue">5.4. PassengerUseGlobalQueue <on|off></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
|
+
“queuing-behind-long-running-request” 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 <on|off></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.
|
1183
|
+
<h3 id="PassengerDefaultUser">5.6. PassengerDefaultUser <username></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.
|
1110
|
-
<h4 id="_passengermaxpoolsize_lt_integer_gt">5.
|
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 <integer></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.
|
1215
|
+
<h4 id="_passengermaxinstancesperapp_lt_integer_gt">5.7.2. PassengerMaxInstancesPerApp <integer></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.
|
1146
|
-
<div class="para"><p>The maximum number of seconds that
|
1147
|
-
|
1148
|
-
|
1149
|
-
memory.</p></div>
|
1225
|
+
<h4 id="PassengerPoolIdleTime">5.7.3. PassengerPoolIdleTime <integer></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.
|
1161
|
-
<h4 id="_railsautodetect_lt_on_off_gt">5.
|
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 <on|off></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
|
</VirtualHost></tt></pre>
|
1188
1267
|
</div></div>
|
1189
|
-
<h4 id="RailsBaseURI">5.
|
1268
|
+
<h4 id="RailsBaseURI">5.8.2. RailsBaseURI <uri></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.
|
1275
|
+
<h4 id="RailsAllowModRewrite">5.8.3. RailsAllowModRewrite <on|off></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.
|
1280
|
+
<h4 id="rails_env">5.8.4. RailsEnv <string></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.
|
1284
|
+
<h4 id="RailsSpawnMethod">5.8.5. RailsSpawnMethod <string></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
|
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.
|
1264
|
-
<h4 id="_rackautodetect_lt_on_off_gt">5.
|
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 <on|off></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
|
</VirtualHost></tt></pre>
|
1291
1371
|
</div></div>
|
1292
|
-
<h4 id="RackBaseURI">5.
|
1372
|
+
<h4 id="RackBaseURI">5.9.2. RackBaseURI <uri></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.
|
1379
|
+
<h4 id="rack_env">5.9.3. RackEnv <string></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.
|
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.
|
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.
|
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.
|
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-
|
2182
|
+
Last updated 2008-12-01 14:21:18 CEST
|
2101
2183
|
</div>
|
2102
2184
|
</div>
|
2103
2185
|
</body>
|
data/doc/Users guide.txt
CHANGED
@@ -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
|
603
|
-
|
604
|
-
|
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
|
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 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 & 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 <boost/shared_ptr.hpp></span>
|
41
|
+
<a name="l00024"></a>00024 <span class="preprocessor">#include <boost/thread/mutex.hpp></span>
|
42
|
+
<a name="l00025"></a>00025
|
43
|
+
<a name="l00026"></a>00026 <span class="preprocessor">#include <sys/types.h></span>
|
44
|
+
<a name="l00027"></a>00027 <span class="preprocessor">#include <sys/stat.h></span>
|
45
|
+
<a name="l00028"></a>00028 <span class="preprocessor">#include <sys/wait.h></span>
|
46
|
+
<a name="l00029"></a>00029 <span class="preprocessor">#include <sys/socket.h></span>
|
47
|
+
<a name="l00030"></a>00030 <span class="preprocessor">#include <cstdio></span>
|
48
|
+
<a name="l00031"></a>00031 <span class="preprocessor">#include <cstdlib></span>
|
49
|
+
<a name="l00032"></a>00032 <span class="preprocessor">#include <limits.h></span>
|
50
|
+
<a name="l00033"></a>00033 <span class="preprocessor">#include <errno.h></span>
|
51
|
+
<a name="l00034"></a>00034 <span class="preprocessor">#include <unistd.h></span>
|
52
|
+
<a name="l00035"></a>00035 <span class="preprocessor">#include <signal.h></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->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"> * <h2>Implementation notes</h2></span>
|
105
|
+
<a name="l00088"></a>00088 <span class="comment"> *</span>
|
106
|
+
<a name="l00089"></a>00089 <span class="comment"> * <h3>Separate server executable</h3></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"> * <h3>Anonymous server socket</h3></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 (<tt>socketpair()</tt>) and file descriptor</span>
|
139
|
+
<a name="l00122"></a>00122 <span class="comment"> * passing. It allows one to emulate <tt>accept()</tt>. 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 && 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<SharedData> 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->data = data;
|
186
|
+
<a name="l00169"></a>00169 this->pid = pid;
|
187
|
+
<a name="l00170"></a>00170 this-><span class="keywordtype">id</span> = id;
|
188
|
+
<a name="l00171"></a>00171 this->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->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->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->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->server);
|
267
|
+
<a name="l00250"></a>00250 mutex::scoped_lock l(data->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->server);
|
273
|
+
<a name="l00256"></a>00256 mutex::scoped_lock l(data->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->server);
|
279
|
+
<a name="l00262"></a>00262 mutex::scoped_lock l(data->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->server);
|
285
|
+
<a name="l00268"></a>00268 mutex::scoped_lock l(data->lock);
|
286
|
+
<a name="l00269"></a>00269 vector<string> 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->server);
|
295
|
+
<a name="l00278"></a>00278 mutex::scoped_lock l(data->lock);
|
296
|
+
<a name="l00279"></a>00279 vector<string> 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->server);
|
305
|
+
<a name="l00288"></a>00288 mutex::scoped_lock l(data->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->server);
|
311
|
+
<a name="l00294"></a>00294 boost::mutex::scoped_lock l(data->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->server);
|
318
|
+
<a name="l00301"></a>00301 mutex::scoped_lock l(data->lock);
|
319
|
+
<a name="l00302"></a>00302 vector<string> 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> &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> &lowestUser = <span class="stringliteral">"nobody"</span>,
|
330
|
+
<a name="l00313"></a>00313 <span class="keyword">const</span> <span class="keywordtype">string</span> &environment = <span class="stringliteral">"production"</span>,
|
331
|
+
<a name="l00314"></a>00314 <span class="keyword">const</span> <span class="keywordtype">string</span> &spawnMethod = <span class="stringliteral">"smart"</span>,
|
332
|
+
<a name="l00315"></a>00315 <span class="keyword">const</span> <span class="keywordtype">string</span> &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->server);
|
336
|
+
<a name="l00319"></a>00319 mutex::scoped_lock l(data->lock);
|
337
|
+
<a name="l00320"></a>00320 vector<string> 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> &) {
|
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> &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 <tt>serverPid == 0</tt>.</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 <tt>serverSocket == -1</tt>.</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 && serverPid != 0</span>
|
424
|
+
<a name="l00407"></a>00407 <span class="comment"> * @post serverSocket == -1 && 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 && 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> <<
|
440
|
+
<a name="l00423"></a>00423 serverPid << <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 && InterruptableCalls::time(NULL) < 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 > 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 && 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 > 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 && errno == EINTR);
|
541
|
+
<a name="l00524"></a>00524 <span class="keywordflow">if</span> (ret == -1 && 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> << filename <<
|
544
|
+
<a name="l00527"></a>00527 <span class="stringliteral">"': "</span> << strerror(e) << <span class="stringliteral">" ("</span> << e << <span class="stringliteral">")"</span> << endl <<
|
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 <tt>user</tt> 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> &serverExecutable,
|
576
|
+
<a name="l00559"></a>00559 <span class="keyword">const</span> <span class="keywordtype">string</span> &spawnServerCommand,
|
577
|
+
<a name="l00560"></a>00560 <span class="keyword">const</span> <span class="keywordtype">string</span> &logFile = <span class="stringliteral">""</span>,
|
578
|
+
<a name="l00561"></a>00561 <span class="keyword">const</span> <span class="keywordtype">string</span> &rubyCommand = <span class="stringliteral">"ruby"</span>,
|
579
|
+
<a name="l00562"></a>00562 <span class="keyword">const</span> <span class="keywordtype">string</span> &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->get(...);</span>
|
614
|
+
<a name="l00597"></a>00597 <span class="comment"> * Application::SessionPtr session2 = pool->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->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->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> &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> &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&#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 && 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<ApplicationPoolServer> 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
|
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>
|