passenger 1.0.4 → 1.0.5

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

Potentially problematic release.


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

Files changed (98) hide show
  1. data/Rakefile +7 -4
  2. data/bin/passenger-install-apache2-module +3 -1
  3. data/doc/Users guide.html +1 -1
  4. data/doc/cxxapi/ApplicationPoolClientServer_8h-source.html +1 -1
  5. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +497 -496
  6. data/doc/cxxapi/ApplicationPool_8h-source.html +1 -1
  7. data/doc/cxxapi/Application_8h-source.html +1 -1
  8. data/doc/cxxapi/Configuration_8h-source.html +2 -2
  9. data/doc/cxxapi/DummySpawnManager_8h-source.html +1 -1
  10. data/doc/cxxapi/Exceptions_8h-source.html +1 -1
  11. data/doc/cxxapi/Hooks_8h-source.html +1 -1
  12. data/doc/cxxapi/Logging_8h-source.html +1 -1
  13. data/doc/cxxapi/MessageChannel_8h-source.html +224 -198
  14. data/doc/cxxapi/SpawnManager_8h-source.html +1 -1
  15. data/doc/cxxapi/StandardApplicationPool_8h-source.html +1 -1
  16. data/doc/cxxapi/Utils_8h-source.html +1 -1
  17. data/doc/cxxapi/annotated.html +1 -1
  18. data/doc/cxxapi/classClient-members.html +1 -1
  19. data/doc/cxxapi/classClient.html +1 -1
  20. data/doc/cxxapi/classPassenger_1_1Application-members.html +1 -1
  21. data/doc/cxxapi/classPassenger_1_1Application.html +1 -1
  22. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +1 -1
  23. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +1 -1
  24. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +1 -1
  25. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +1 -1
  26. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +1 -1
  27. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +1 -1
  28. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +1 -1
  29. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +1 -1
  30. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +1 -1
  31. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +1 -1
  32. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +1 -1
  33. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +1 -1
  34. data/doc/cxxapi/classPassenger_1_1IOException-members.html +1 -1
  35. data/doc/cxxapi/classPassenger_1_1IOException.html +1 -1
  36. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +1 -1
  37. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +1 -1
  38. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +1 -1
  39. data/doc/cxxapi/classPassenger_1_1SpawnException.html +1 -1
  40. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +1 -1
  41. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +1 -1
  42. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +1 -1
  43. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +1 -1
  44. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +1 -1
  45. data/doc/cxxapi/classPassenger_1_1SystemException.html +1 -1
  46. data/doc/cxxapi/definitions_8h-source.html +1 -1
  47. data/doc/cxxapi/files.html +1 -1
  48. data/doc/cxxapi/functions.html +1 -1
  49. data/doc/cxxapi/functions_func.html +1 -1
  50. data/doc/cxxapi/functions_type.html +1 -1
  51. data/doc/cxxapi/graph_legend.html +1 -1
  52. data/doc/cxxapi/graph_legend.png +0 -0
  53. data/doc/cxxapi/group__Configuration.html +3 -3
  54. data/doc/cxxapi/group__Configuration.png +0 -0
  55. data/doc/cxxapi/group__Core.html +1 -1
  56. data/doc/cxxapi/group__Core.png +0 -0
  57. data/doc/cxxapi/group__Exceptions.html +1 -1
  58. data/doc/cxxapi/group__Hooks.html +1 -1
  59. data/doc/cxxapi/group__Hooks.png +0 -0
  60. data/doc/cxxapi/group__Support.html +1 -1
  61. data/doc/cxxapi/hierarchy.html +1 -1
  62. data/doc/cxxapi/inherit__graph__0.png +0 -0
  63. data/doc/cxxapi/inherit__graph__1.png +0 -0
  64. data/doc/cxxapi/inherit__graph__2.png +0 -0
  65. data/doc/cxxapi/inherit__graph__3.png +0 -0
  66. data/doc/cxxapi/inherit__graph__4.png +0 -0
  67. data/doc/cxxapi/inherit__graph__5.png +0 -0
  68. data/doc/cxxapi/inherit__graph__6.png +0 -0
  69. data/doc/cxxapi/inherit__graph__7.png +0 -0
  70. data/doc/cxxapi/inherit__graph__8.png +0 -0
  71. data/doc/cxxapi/inherit__graph__9.png +0 -0
  72. data/doc/cxxapi/inherits.html +1 -1
  73. data/doc/cxxapi/main.html +1 -1
  74. data/doc/cxxapi/modules.html +1 -1
  75. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +1 -1
  76. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +1 -1
  77. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +1 -1
  78. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +1 -1
  79. data/doc/rdoc/created.rid +1 -1
  80. data/doc/rdoc/files/DEVELOPERS_TXT.html +1 -1
  81. data/doc/rdoc/files/ext/passenger/native_support_c.html +1 -1
  82. data/doc/rdoc/files/lib/passenger/abstract_server_rb.html +1 -1
  83. data/doc/rdoc/files/lib/passenger/application_spawner_rb.html +1 -1
  84. data/doc/rdoc/files/lib/passenger/dependencies_rb.html +1 -1
  85. data/doc/rdoc/files/lib/passenger/framework_spawner_rb.html +1 -1
  86. data/doc/rdoc/files/lib/passenger/request_handler_rb.html +1 -1
  87. data/doc/rdoc/files/lib/passenger/spawn_manager_rb.html +1 -1
  88. data/doc/rdoc/files/lib/passenger/utils_rb.html +1 -1
  89. data/ext/apache2/Configuration.h +1 -1
  90. data/ext/apache2/MessageChannel.h +37 -11
  91. data/ext/passenger/native_support.c +36 -10
  92. data/lib/passenger/templates/app_exited_during_initialization.html.erb +3 -2
  93. data/lib/passenger/templates/welcome.txt.erb +1 -1
  94. data/misc/render_error_pages.rb +3 -0
  95. data/test/stub/{mycook → rails_apps/mycook}/config/environments/test.rb +0 -0
  96. metadata +12 -14
  97. data/test/stub/apache2/httpd.conf +0 -75
  98. data/test/stub/railsapp-without-version-spec/config/environments/test.rb +0 -22
data/Rakefile CHANGED
@@ -27,7 +27,7 @@ require 'passenger/platform_info'
27
27
  ##### Configuration
28
28
 
29
29
  # Don't forget to edit Configuration.h too
30
- PACKAGE_VERSION = "1.0.4"
30
+ PACKAGE_VERSION = "1.0.5"
31
31
 
32
32
  include PlatformInfo
33
33
  APXS2.nil? and raise "Could not find 'apxs' or 'apxs2'."
@@ -186,17 +186,20 @@ class TEST
186
186
  'MessageChannelTest.o' => %w(MessageChannelTest.cpp ../ext/apache2/MessageChannel.h),
187
187
  'SpawnManagerTest.o' => %w(SpawnManagerTest.cpp
188
188
  ../ext/apache2/SpawnManager.h
189
- ../ext/apache2/Application.h),
189
+ ../ext/apache2/Application.h
190
+ ../ext/apache2/MessageChannel.h),
190
191
  'ApplicationPoolServerTest.o' => %w(ApplicationPoolServerTest.cpp
191
192
  ../ext/apache2/StandardApplicationPool.h
192
- ../ext/apache2/ApplicationPoolClientServer.h),
193
+ ../ext/apache2/ApplicationPoolClientServer.h
194
+ ../ext/apache2/MessageChannel.h),
193
195
  'ApplicationPoolServer_ApplicationPoolTest.o' => %w(ApplicationPoolServer_ApplicationPoolTest.cpp
194
196
  ApplicationPoolTest.cpp
195
197
  ../ext/apache2/ApplicationPoolClientServer.h
196
198
  ../ext/apache2/ApplicationPool.h
197
199
  ../ext/apache2/StandardApplicationPool.h
198
200
  ../ext/apache2/SpawnManager.h
199
- ../ext/apache2/Application.h),
201
+ ../ext/apache2/Application.h
202
+ ../ext/apache2/MessageChannel.h),
200
203
  'StandardApplicationPoolTest.o' => %w(StandardApplicationPoolTest.cpp
201
204
  ApplicationPoolTest.cpp
202
205
  ../ext/apache2/ApplicationPool.h
@@ -35,6 +35,8 @@ class Installer
35
35
  PASSENGER_WEBSITE = "http://www.modrails.com/"
36
36
  PHUSION_WEBSITE = "www.phusion.nl"
37
37
  USERS_GUIDE = "#{PASSENGER_ROOT}/doc/Users guide.html"
38
+ File.read("#{PASSENGER_ROOT}/Rakefile") =~ /^PACKAGE_VERSION = "(.*)"$/
39
+ PASSENGER_VERSION = $1
38
40
 
39
41
  REQUIRED_DEPENDENCIES = [
40
42
  Dependencies::GCC,
@@ -77,7 +79,7 @@ private
77
79
  end
78
80
 
79
81
  def show_welcome_screen
80
- render_template 'welcome'
82
+ render_template 'welcome', :version => PASSENGER_VERSION
81
83
  wait
82
84
  end
83
85
 
@@ -1435,7 +1435,7 @@ Attribution-Share Alike 3.0 Unported License</a>.</p></div>
1435
1435
  </div>
1436
1436
  <div id="footer">
1437
1437
  <div id="footer-text">
1438
- Last updated 2008-05-01 20:10:22 CEST
1438
+ Last updated 2008-05-07 20:28:20 CEST
1439
1439
  </div>
1440
1440
  </div>
1441
1441
  </body>
@@ -666,7 +666,7 @@
666
666
  <a name="l00651"></a>00651 } <span class="comment">// namespace Passenger</span>
667
667
  <a name="l00652"></a>00652
668
668
  <a name="l00653"></a>00653 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_APPLICATION_POOL_CLIENT_SERVER_H_ */</span>
669
- </pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Thu May 1 20:23:46 2008 for Passenger by&nbsp;
669
+ </pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Wed May 7 20:28:18 2008 for Passenger by&nbsp;
670
670
  <a href="http://www.doxygen.org/index.html">
671
671
  <img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
672
672
  </body>
@@ -41,504 +41,505 @@
41
41
  <a name="l00026"></a>00026 <span class="preprocessor">#include &lt;cstdlib&gt;</span>
42
42
  <a name="l00027"></a>00027 <span class="preprocessor">#include &lt;errno.h&gt;</span>
43
43
  <a name="l00028"></a>00028 <span class="preprocessor">#include &lt;unistd.h&gt;</span>
44
- <a name="l00029"></a>00029
45
- <a name="l00030"></a>00030 <span class="preprocessor">#include "MessageChannel.h"</span>
46
- <a name="l00031"></a>00031 <span class="preprocessor">#include "ApplicationPool.h"</span>
47
- <a name="l00032"></a>00032 <span class="preprocessor">#include "Application.h"</span>
48
- <a name="l00033"></a>00033 <span class="preprocessor">#include "Exceptions.h"</span>
49
- <a name="l00034"></a>00034 <span class="preprocessor">#include "Logging.h"</span>
50
- <a name="l00035"></a>00035
51
- <a name="l00036"></a>00036 <span class="keyword">namespace </span>Passenger {
52
- <a name="l00037"></a>00037
53
- <a name="l00038"></a>00038 <span class="keyword">using namespace </span>std;
54
- <a name="l00039"></a>00039 <span class="keyword">using namespace </span>boost;
55
- <a name="l00040"></a>00040
56
- <a name="l00041"></a>00041 <span class="comment"></span>
57
- <a name="l00042"></a>00042 <span class="comment">/**</span>
58
- <a name="l00043"></a>00043 <span class="comment"> * Multi-process usage support for ApplicationPool.</span>
59
- <a name="l00044"></a>00044 <span class="comment"> *</span>
60
- <a name="l00045"></a>00045 <span class="comment"> * ApplicationPoolServer implements a client/server architecture for ApplicationPool.</span>
61
- <a name="l00046"></a>00046 <span class="comment"> * This allows one to use ApplicationPool in a multi-process environment (unlike</span>
62
- <a name="l00047"></a>00047 <span class="comment"> * StandardApplicationPool). The cache/pool data is stored in the server. Different</span>
63
- <a name="l00048"></a>00048 <span class="comment"> * processes can then access the pool through the server.</span>
64
- <a name="l00049"></a>00049 <span class="comment"> *</span>
65
- <a name="l00050"></a>00050 <span class="comment"> * ApplicationPoolServer itself does not inherit ApplicationPool. Instead, it returns</span>
66
- <a name="l00051"></a>00051 <span class="comment"> * an ApplicationPool object via the connect() call. For example:</span>
67
- <a name="l00052"></a>00052 <span class="comment"> * @code</span>
68
- <a name="l00053"></a>00053 <span class="comment"> * // Create an ApplicationPoolServer.</span>
69
- <a name="l00054"></a>00054 <span class="comment"> * ApplicationPoolServer server(...);</span>
70
- <a name="l00055"></a>00055 <span class="comment"> * </span>
71
- <a name="l00056"></a>00056 <span class="comment"> * // Now fork a child process, like Apache's prefork MPM eventually will.</span>
72
- <a name="l00057"></a>00057 <span class="comment"> * pid_t pid = fork();</span>
73
- <a name="l00058"></a>00058 <span class="comment"> * if (pid == 0) {</span>
74
- <a name="l00059"></a>00059 <span class="comment"> * // Child process</span>
75
- <a name="l00060"></a>00060 <span class="comment"> * </span>
76
- <a name="l00061"></a>00061 <span class="comment"> * // Connect to the server. After connection, we have an ApplicationPool</span>
77
- <a name="l00062"></a>00062 <span class="comment"> * // object!</span>
78
- <a name="l00063"></a>00063 <span class="comment"> * ApplicationPoolPtr pool(server.connect());</span>
79
- <a name="l00064"></a>00064 <span class="comment"> *</span>
80
- <a name="l00065"></a>00065 <span class="comment"> * // We don't need to connect to the server anymore, so we detach from it.</span>
81
- <a name="l00066"></a>00066 <span class="comment"> * // This frees up some resources, such as file descriptors.</span>
82
- <a name="l00067"></a>00067 <span class="comment"> * server.detach();</span>
83
- <a name="l00068"></a>00068 <span class="comment"> *</span>
84
- <a name="l00069"></a>00069 <span class="comment"> * ApplicationPool::SessionPtr session(pool-&gt;get("/home/webapps/foo"));</span>
85
- <a name="l00070"></a>00070 <span class="comment"> * do_something_with(session);</span>
86
- <a name="l00071"></a>00071 <span class="comment"> *</span>
87
- <a name="l00072"></a>00072 <span class="comment"> * _exit(0);</span>
88
- <a name="l00073"></a>00073 <span class="comment"> * } else {</span>
89
- <a name="l00074"></a>00074 <span class="comment"> * // Parent process</span>
90
- <a name="l00075"></a>00075 <span class="comment"> * waitpid(pid, NULL, 0);</span>
91
- <a name="l00076"></a>00076 <span class="comment"> * }</span>
92
- <a name="l00077"></a>00077 <span class="comment"> * @endcode</span>
93
- <a name="l00078"></a>00078 <span class="comment"> *</span>
94
- <a name="l00079"></a>00079 <span class="comment"> * &lt;h2&gt;Implementation notes&lt;/h2&gt;</span>
95
- <a name="l00080"></a>00080 <span class="comment"> *</span>
96
- <a name="l00081"></a>00081 <span class="comment"> * &lt;h3&gt;Separate server executable&lt;/h3&gt;</span>
97
- <a name="l00082"></a>00082 <span class="comment"> * The actual server is implemented in ApplicationPoolServerExecutable.cpp, this class is</span>
98
- <a name="l00083"></a>00083 <span class="comment"> * just a convenience class for starting/stopping the server executable and connecting</span>
99
- <a name="l00084"></a>00084 <span class="comment"> * to it.</span>
100
- <a name="l00085"></a>00085 <span class="comment"> *</span>
101
- <a name="l00086"></a>00086 <span class="comment"> * In the past, the server logic itself was implemented in this class. This implies that</span>
102
- <a name="l00087"></a>00087 <span class="comment"> * the ApplicationPool server ran inside the Apache process. This presented us with several</span>
103
- <a name="l00088"></a>00088 <span class="comment"> * problems:</span>
104
- <a name="l00089"></a>00089 <span class="comment"> * - Because of the usage of threads in the ApplicationPool server, the Apache VM size would</span>
105
- <a name="l00090"></a>00090 <span class="comment"> * go way up. This gave people the (wrong) impression that Passenger uses a lot of memory,</span>
106
- <a name="l00091"></a>00091 <span class="comment"> * or that it leaks memory.</span>
107
- <a name="l00092"></a>00092 <span class="comment"> * - Although it's not entirely confirmed, we suspect that it caused heap fragmentation as</span>
108
- <a name="l00093"></a>00093 <span class="comment"> * well. Apache allocates lots and lots of small objects on the heap, and ApplicationPool</span>
109
- <a name="l00094"></a>00094 <span class="comment"> * server isn't exactly helping. This too gave people the (wrong) impression that</span>
110
- <a name="l00095"></a>00095 <span class="comment"> * Passenger leaks memory.</span>
111
- <a name="l00096"></a>00096 <span class="comment"> * - It would unnecessarily bloat the VM size of Apache worker processes.</span>
112
- <a name="l00097"></a>00097 <span class="comment"> * - We had to resort to all kinds of tricks to make sure that fork()ing a process doesn't</span>
113
- <a name="l00098"></a>00098 <span class="comment"> * result in file descriptor leaks.</span>
114
- <a name="l00099"></a>00099 <span class="comment"> * - Despite everything, there was still a small chance that file descriptor leaks would</span>
115
- <a name="l00100"></a>00100 <span class="comment"> * occur, and this could not be fixed. The reason for this is that the Apache control</span>
116
- <a name="l00101"></a>00101 <span class="comment"> * process may call fork() right after the ApplicationPool server has established a new</span>
117
- <a name="l00102"></a>00102 <span class="comment"> * connection with a client.</span>
118
- <a name="l00103"></a>00103 <span class="comment"> *</span>
119
- <a name="l00104"></a>00104 <span class="comment"> * Because of these problems, it was decided to split the ApplicationPool server to a</span>
120
- <a name="l00105"></a>00105 <span class="comment"> * separate executable. This comes with no performance hit.</span>
121
- <a name="l00106"></a>00106 <span class="comment"> *</span>
122
- <a name="l00107"></a>00107 <span class="comment"> * &lt;h3&gt;Anonymous server socket&lt;/h3&gt;</span>
123
- <a name="l00108"></a>00108 <span class="comment"> * Notice that ApplicationPoolServer does do not use TCP sockets at all, or even named Unix</span>
124
- <a name="l00109"></a>00109 <span class="comment"> * sockets, despite being a server that can handle multiple clients! So ApplicationPoolServer</span>
125
- <a name="l00110"></a>00110 <span class="comment"> * will expose no open ports or temporary Unix socket files. Only child processes are able</span>
126
- <a name="l00111"></a>00111 <span class="comment"> * to use the ApplicationPoolServer.</span>
127
- <a name="l00112"></a>00112 <span class="comment"> *</span>
128
- <a name="l00113"></a>00113 <span class="comment"> * This is implemented through anonymous Unix sockets (&lt;tt&gt;socketpair()&lt;/tt&gt;) and file descriptor</span>
129
- <a name="l00114"></a>00114 <span class="comment"> * passing. It allows one to emulate &lt;tt&gt;accept()&lt;/tt&gt;. ApplicationPoolServer is connected to</span>
130
- <a name="l00115"></a>00115 <span class="comment"> * the server executable through a Unix socket pair. connect() sends a connect request to the</span>
131
- <a name="l00116"></a>00116 <span class="comment"> * server through that socket. The server will then create a new socket pair, and pass one of</span>
132
- <a name="l00117"></a>00117 <span class="comment"> * them back. This new socket pair represents the newly established connection.</span>
133
- <a name="l00118"></a>00118 <span class="comment"> *</span>
134
- <a name="l00119"></a>00119 <span class="comment"> * @ingroup Support</span>
135
- <a name="l00120"></a>00120 <span class="comment"> */</span>
136
- <a name="l00121"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html">00121</a> <span class="keyword">class </span><a class="code" href="classPassenger_1_1ApplicationPoolServer.html" title="Multi-process usage support for ApplicationPool.">ApplicationPoolServer</a> {
137
- <a name="l00122"></a>00122 <span class="keyword">private</span>:<span class="comment"></span>
138
- <a name="l00123"></a>00123 <span class="comment"> /**</span>
139
- <a name="l00124"></a>00124 <span class="comment"> * Contains data shared between RemoteSession and Client.</span>
140
- <a name="l00125"></a>00125 <span class="comment"> * Since RemoteSession and Client have different life times, i.e. one may be</span>
141
- <a name="l00126"></a>00126 <span class="comment"> * destroyed before the other, they both use a smart pointer that points to</span>
142
- <a name="l00127"></a>00127 <span class="comment"> * a SharedData. This way, the SharedData object is only destroyed when</span>
143
- <a name="l00128"></a>00128 <span class="comment"> * both the RemoteSession and the Client object has been destroyed.</span>
144
- <a name="l00129"></a>00129 <span class="comment"> */</span>
145
- <a name="l00130"></a>00130 <span class="keyword">struct </span>SharedData {<span class="comment"></span>
146
- <a name="l00131"></a>00131 <span class="comment"> /**</span>
147
- <a name="l00132"></a>00132 <span class="comment"> * The socket connection to the ApplicationPool server, as was</span>
148
- <a name="l00133"></a>00133 <span class="comment"> * established by ApplicationPoolServer::connect().</span>
149
- <a name="l00134"></a>00134 <span class="comment"> */</span>
150
- <a name="l00135"></a>00135 <span class="keywordtype">int</span> server;
151
- <a name="l00136"></a>00136
152
- <a name="l00137"></a>00137 ~SharedData() {
153
- <a name="l00138"></a>00138 close(server);
154
- <a name="l00139"></a>00139 }
155
- <a name="l00140"></a>00140 };
156
- <a name="l00141"></a>00141
157
- <a name="l00142"></a>00142 <span class="keyword">typedef</span> shared_ptr&lt;SharedData&gt; SharedDataPtr;
158
- <a name="l00143"></a>00143 <span class="comment"></span>
159
- <a name="l00144"></a>00144 <span class="comment"> /**</span>
160
- <a name="l00145"></a>00145 <span class="comment"> * An Application::Session which works together with ApplicationPoolServer.</span>
161
- <a name="l00146"></a>00146 <span class="comment"> */</span>
162
- <a name="l00147"></a>00147 <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 application instance.">Application</a>::Session {
163
- <a name="l00148"></a>00148 <span class="keyword">private</span>:
164
- <a name="l00149"></a>00149 SharedDataPtr data;
165
- <a name="l00150"></a>00150 <span class="keywordtype">int</span> id;
166
- <a name="l00151"></a>00151 <span class="keywordtype">int</span> reader;
167
- <a name="l00152"></a>00152 <span class="keywordtype">int</span> writer;
168
- <a name="l00153"></a>00153 pid_t pid;
169
- <a name="l00154"></a>00154 <span class="keyword">public</span>:
170
- <a name="l00155"></a>00155 RemoteSession(SharedDataPtr data, pid_t pid, <span class="keywordtype">int</span> <span class="keywordtype">id</span>, <span class="keywordtype">int</span> reader, <span class="keywordtype">int</span> writer) {
171
- <a name="l00156"></a>00156 this-&gt;data = data;
172
- <a name="l00157"></a>00157 this-&gt;pid = pid;
173
- <a name="l00158"></a>00158 this-&gt;<span class="keywordtype">id</span> = id;
174
- <a name="l00159"></a>00159 this-&gt;reader = reader;
175
- <a name="l00160"></a>00160 this-&gt;writer = writer;
176
- <a name="l00161"></a>00161 }
177
- <a name="l00162"></a>00162
178
- <a name="l00163"></a>00163 <span class="keyword">virtual</span> ~RemoteSession() {
179
- <a name="l00164"></a>00164 closeReader();
180
- <a name="l00165"></a>00165 closeWriter();
181
- <a name="l00166"></a>00166 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a>(data-&gt;server).write(<span class="stringliteral">"close"</span>, <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(<span class="keywordtype">id</span>).c_str(), NULL);
182
- <a name="l00167"></a>00167 }
183
- <a name="l00168"></a>00168
184
- <a name="l00169"></a>00169 <span class="keyword">virtual</span> <span class="keywordtype">int</span> getReader()<span class="keyword"> const </span>{
185
- <a name="l00170"></a>00170 <span class="keywordflow">return</span> reader;
186
- <a name="l00171"></a>00171 }
187
- <a name="l00172"></a>00172
188
- <a name="l00173"></a>00173 <span class="keyword">virtual</span> <span class="keywordtype">void</span> closeReader() {
189
- <a name="l00174"></a>00174 <span class="keywordflow">if</span> (reader != -1) {
190
- <a name="l00175"></a>00175 close(reader);
191
- <a name="l00176"></a>00176 reader = -1;
192
- <a name="l00177"></a>00177 }
193
- <a name="l00178"></a>00178 }
194
- <a name="l00179"></a>00179
195
- <a name="l00180"></a>00180 <span class="keyword">virtual</span> <span class="keywordtype">int</span> getWriter()<span class="keyword"> const </span>{
196
- <a name="l00181"></a>00181 <span class="keywordflow">return</span> writer;
197
- <a name="l00182"></a>00182 }
198
- <a name="l00183"></a>00183
199
- <a name="l00184"></a>00184 <span class="keyword">virtual</span> <span class="keywordtype">void</span> closeWriter() {
200
- <a name="l00185"></a>00185 <span class="keywordflow">if</span> (writer != -1) {
201
- <a name="l00186"></a>00186 close(writer);
202
- <a name="l00187"></a>00187 writer = -1;
203
- <a name="l00188"></a>00188 }
204
- <a name="l00189"></a>00189 }
205
- <a name="l00190"></a>00190
206
- <a name="l00191"></a>00191 <span class="keyword">virtual</span> pid_t getPid()<span class="keyword"> const </span>{
207
- <a name="l00192"></a>00192 <span class="keywordflow">return</span> pid;
208
- <a name="l00193"></a>00193 }
209
- <a name="l00194"></a>00194 };
210
- <a name="l00195"></a>00195 <span class="comment"></span>
211
- <a name="l00196"></a>00196 <span class="comment"> /**</span>
212
- <a name="l00197"></a>00197 <span class="comment"> * An ApplicationPool implementation that works together with ApplicationPoolServer.</span>
213
- <a name="l00198"></a>00198 <span class="comment"> * It doesn't do much by itself, its job is mostly to forward queries/commands to</span>
214
- <a name="l00199"></a>00199 <span class="comment"> * the server and returning the result. Most of the logic is in the server executable.</span>
215
- <a name="l00200"></a>00200 <span class="comment"> */</span>
216
- <a name="l00201"></a>00201 <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> {
217
- <a name="l00202"></a>00202 <span class="keyword">private</span>:
218
- <a name="l00203"></a>00203 SharedDataPtr data;
219
- <a name="l00204"></a>00204
220
- <a name="l00205"></a>00205 <span class="keyword">public</span>:<span class="comment"></span>
221
- <a name="l00206"></a>00206 <span class="comment"> /**</span>
222
- <a name="l00207"></a>00207 <span class="comment"> * Create a new Client.</span>
223
- <a name="l00208"></a>00208 <span class="comment"> *</span>
224
- <a name="l00209"></a>00209 <span class="comment"> * @param sock The newly established socket connection with the ApplicationPoolServer.</span>
225
- <a name="l00210"></a>00210 <span class="comment"> */</span>
226
- <a name="l00211"></a>00211 Client(<span class="keywordtype">int</span> sock) {
227
- <a name="l00212"></a>00212 data = <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(<span class="keyword">new</span> SharedData());
228
- <a name="l00213"></a>00213 data-&gt;server = sock;
229
- <a name="l00214"></a>00214 }
230
- <a name="l00215"></a>00215
231
- <a name="l00216"></a>00216 <span class="keyword">virtual</span> <span class="keywordtype">void</span> clear() {
232
- <a name="l00217"></a>00217 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
233
- <a name="l00218"></a>00218 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);
234
- <a name="l00219"></a>00219 }
235
- <a name="l00220"></a>00220
236
- <a name="l00221"></a>00221 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMaxIdleTime(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> seconds) {
237
- <a name="l00222"></a>00222 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
238
- <a name="l00223"></a>00223 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);
239
- <a name="l00224"></a>00224 }
240
- <a name="l00225"></a>00225
241
- <a name="l00226"></a>00226 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMax(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> max) {
242
- <a name="l00227"></a>00227 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
243
- <a name="l00228"></a>00228 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);
244
- <a name="l00229"></a>00229 }
245
- <a name="l00230"></a>00230
246
- <a name="l00231"></a>00231 <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> getActive()<span class="keyword"> const </span>{
247
- <a name="l00232"></a>00232 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
248
- <a name="l00233"></a>00233 vector&lt;string&gt; args;
249
- <a name="l00234"></a>00234
250
- <a name="l00235"></a>00235 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);
251
- <a name="l00236"></a>00236 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args);
252
- <a name="l00237"></a>00237 <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());
253
- <a name="l00238"></a>00238 }
254
- <a name="l00239"></a>00239
255
- <a name="l00240"></a>00240 <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> getCount()<span class="keyword"> const </span>{
256
- <a name="l00241"></a>00241 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
257
- <a name="l00242"></a>00242 vector&lt;string&gt; args;
258
- <a name="l00243"></a>00243
259
- <a name="l00244"></a>00244 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);
260
- <a name="l00245"></a>00245 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args);
261
- <a name="l00246"></a>00246 <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());
262
- <a name="l00247"></a>00247 }
263
- <a name="l00248"></a>00248
264
- <a name="l00249"></a>00249 <span class="keyword">virtual</span> pid_t getSpawnServerPid()<span class="keyword"> const </span>{
265
- <a name="l00250"></a>00250 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
266
- <a name="l00251"></a>00251 vector&lt;string&gt; args;
267
- <a name="l00252"></a>00252
268
- <a name="l00253"></a>00253 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);
269
- <a name="l00254"></a>00254 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args);
270
- <a name="l00255"></a>00255 <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());
271
- <a name="l00256"></a>00256 }
272
- <a name="l00257"></a>00257
273
- <a name="l00258"></a>00258 <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>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot, <span class="keywordtype">bool</span> lowerPrivilege = <span class="keyword">true</span>,
274
- <a name="l00259"></a>00259 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;lowestUser = <span class="stringliteral">"nobody"</span>) {
275
- <a name="l00260"></a>00260 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
276
- <a name="l00261"></a>00261 vector&lt;string&gt; args;
277
- <a name="l00262"></a>00262 <span class="keywordtype">int</span> reader, writer;
278
- <a name="l00263"></a>00263
279
- <a name="l00264"></a>00264 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(),
280
- <a name="l00265"></a>00265 (lowerPrivilege) ? <span class="stringliteral">"true"</span> : <span class="stringliteral">"false"</span>,
281
- <a name="l00266"></a>00266 lowestUser.c_str(), NULL);
282
- <a name="l00267"></a>00267 <span class="keywordflow">if</span> (!channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args)) {
283
- <a name="l00268"></a>00268 <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 closed the connection."</span>);
284
- <a name="l00269"></a>00269 }
285
- <a name="l00270"></a>00270 <span class="keywordflow">if</span> (args[0] == <span class="stringliteral">"ok"</span>) {
286
- <a name="l00271"></a>00271 reader = 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>();
287
- <a name="l00272"></a>00272 writer = 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>();
288
- <a name="l00273"></a>00273 <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(data, <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]), reader, writer));
289
- <a name="l00274"></a>00274 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (args[0] == <span class="stringliteral">"SpawnException"</span>) {
290
- <a name="l00275"></a>00275 <span class="keywordflow">if</span> (args[2] == <span class="stringliteral">"true"</span>) {
291
- <a name="l00276"></a>00276 <span class="keywordtype">string</span> errorPage;
292
- <a name="l00277"></a>00277
293
- <a name="l00278"></a>00278 <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)) {
294
- <a name="l00279"></a>00279 <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 closed the connection."</span>);
295
- <a name="l00280"></a>00280 }
296
- <a name="l00281"></a>00281 <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);
297
- <a name="l00282"></a>00282 } <span class="keywordflow">else</span> {
298
- <a name="l00283"></a>00283 <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]);
299
- <a name="l00284"></a>00284 }
300
- <a name="l00285"></a>00285 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (args[0] == <span class="stringliteral">"IOException"</span>) {
301
- <a name="l00286"></a>00286 <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]);
302
- <a name="l00287"></a>00287 } <span class="keywordflow">else</span> {
303
- <a name="l00288"></a>00288 <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 an unknown message."</span>);
304
- <a name="l00289"></a>00289 }
305
- <a name="l00290"></a>00290 }
306
- <a name="l00291"></a>00291 };
307
- <a name="l00292"></a>00292
44
+ <a name="l00029"></a>00029 <span class="preprocessor">#include &lt;signal.h&gt;</span>
45
+ <a name="l00030"></a>00030
46
+ <a name="l00031"></a>00031 <span class="preprocessor">#include "MessageChannel.h"</span>
47
+ <a name="l00032"></a>00032 <span class="preprocessor">#include "ApplicationPool.h"</span>
48
+ <a name="l00033"></a>00033 <span class="preprocessor">#include "Application.h"</span>
49
+ <a name="l00034"></a>00034 <span class="preprocessor">#include "Exceptions.h"</span>
50
+ <a name="l00035"></a>00035 <span class="preprocessor">#include "Logging.h"</span>
51
+ <a name="l00036"></a>00036
52
+ <a name="l00037"></a>00037 <span class="keyword">namespace </span>Passenger {
53
+ <a name="l00038"></a>00038
54
+ <a name="l00039"></a>00039 <span class="keyword">using namespace </span>std;
55
+ <a name="l00040"></a>00040 <span class="keyword">using namespace </span>boost;
56
+ <a name="l00041"></a>00041
57
+ <a name="l00042"></a>00042 <span class="comment"></span>
58
+ <a name="l00043"></a>00043 <span class="comment">/**</span>
59
+ <a name="l00044"></a>00044 <span class="comment"> * Multi-process usage support for ApplicationPool.</span>
60
+ <a name="l00045"></a>00045 <span class="comment"> *</span>
61
+ <a name="l00046"></a>00046 <span class="comment"> * ApplicationPoolServer implements a client/server architecture for ApplicationPool.</span>
62
+ <a name="l00047"></a>00047 <span class="comment"> * This allows one to use ApplicationPool in a multi-process environment (unlike</span>
63
+ <a name="l00048"></a>00048 <span class="comment"> * StandardApplicationPool). The cache/pool data is stored in the server. Different</span>
64
+ <a name="l00049"></a>00049 <span class="comment"> * processes can then access the pool through the server.</span>
65
+ <a name="l00050"></a>00050 <span class="comment"> *</span>
66
+ <a name="l00051"></a>00051 <span class="comment"> * ApplicationPoolServer itself does not inherit ApplicationPool. Instead, it returns</span>
67
+ <a name="l00052"></a>00052 <span class="comment"> * an ApplicationPool object via the connect() call. For example:</span>
68
+ <a name="l00053"></a>00053 <span class="comment"> * @code</span>
69
+ <a name="l00054"></a>00054 <span class="comment"> * // Create an ApplicationPoolServer.</span>
70
+ <a name="l00055"></a>00055 <span class="comment"> * ApplicationPoolServer server(...);</span>
71
+ <a name="l00056"></a>00056 <span class="comment"> * </span>
72
+ <a name="l00057"></a>00057 <span class="comment"> * // Now fork a child process, like Apache's prefork MPM eventually will.</span>
73
+ <a name="l00058"></a>00058 <span class="comment"> * pid_t pid = fork();</span>
74
+ <a name="l00059"></a>00059 <span class="comment"> * if (pid == 0) {</span>
75
+ <a name="l00060"></a>00060 <span class="comment"> * // Child process</span>
76
+ <a name="l00061"></a>00061 <span class="comment"> * </span>
77
+ <a name="l00062"></a>00062 <span class="comment"> * // Connect to the server. After connection, we have an ApplicationPool</span>
78
+ <a name="l00063"></a>00063 <span class="comment"> * // object!</span>
79
+ <a name="l00064"></a>00064 <span class="comment"> * ApplicationPoolPtr pool(server.connect());</span>
80
+ <a name="l00065"></a>00065 <span class="comment"> *</span>
81
+ <a name="l00066"></a>00066 <span class="comment"> * // We don't need to connect to the server anymore, so we detach from it.</span>
82
+ <a name="l00067"></a>00067 <span class="comment"> * // This frees up some resources, such as file descriptors.</span>
83
+ <a name="l00068"></a>00068 <span class="comment"> * server.detach();</span>
84
+ <a name="l00069"></a>00069 <span class="comment"> *</span>
85
+ <a name="l00070"></a>00070 <span class="comment"> * ApplicationPool::SessionPtr session(pool-&gt;get("/home/webapps/foo"));</span>
86
+ <a name="l00071"></a>00071 <span class="comment"> * do_something_with(session);</span>
87
+ <a name="l00072"></a>00072 <span class="comment"> *</span>
88
+ <a name="l00073"></a>00073 <span class="comment"> * _exit(0);</span>
89
+ <a name="l00074"></a>00074 <span class="comment"> * } else {</span>
90
+ <a name="l00075"></a>00075 <span class="comment"> * // Parent process</span>
91
+ <a name="l00076"></a>00076 <span class="comment"> * waitpid(pid, NULL, 0);</span>
92
+ <a name="l00077"></a>00077 <span class="comment"> * }</span>
93
+ <a name="l00078"></a>00078 <span class="comment"> * @endcode</span>
94
+ <a name="l00079"></a>00079 <span class="comment"> *</span>
95
+ <a name="l00080"></a>00080 <span class="comment"> * &lt;h2&gt;Implementation notes&lt;/h2&gt;</span>
96
+ <a name="l00081"></a>00081 <span class="comment"> *</span>
97
+ <a name="l00082"></a>00082 <span class="comment"> * &lt;h3&gt;Separate server executable&lt;/h3&gt;</span>
98
+ <a name="l00083"></a>00083 <span class="comment"> * The actual server is implemented in ApplicationPoolServerExecutable.cpp, this class is</span>
99
+ <a name="l00084"></a>00084 <span class="comment"> * just a convenience class for starting/stopping the server executable and connecting</span>
100
+ <a name="l00085"></a>00085 <span class="comment"> * to it.</span>
101
+ <a name="l00086"></a>00086 <span class="comment"> *</span>
102
+ <a name="l00087"></a>00087 <span class="comment"> * In the past, the server logic itself was implemented in this class. This implies that</span>
103
+ <a name="l00088"></a>00088 <span class="comment"> * the ApplicationPool server ran inside the Apache process. This presented us with several</span>
104
+ <a name="l00089"></a>00089 <span class="comment"> * problems:</span>
105
+ <a name="l00090"></a>00090 <span class="comment"> * - Because of the usage of threads in the ApplicationPool server, the Apache VM size would</span>
106
+ <a name="l00091"></a>00091 <span class="comment"> * go way up. This gave people the (wrong) impression that Passenger uses a lot of memory,</span>
107
+ <a name="l00092"></a>00092 <span class="comment"> * or that it leaks memory.</span>
108
+ <a name="l00093"></a>00093 <span class="comment"> * - Although it's not entirely confirmed, we suspect that it caused heap fragmentation as</span>
109
+ <a name="l00094"></a>00094 <span class="comment"> * well. Apache allocates lots and lots of small objects on the heap, and ApplicationPool</span>
110
+ <a name="l00095"></a>00095 <span class="comment"> * server isn't exactly helping. This too gave people the (wrong) impression that</span>
111
+ <a name="l00096"></a>00096 <span class="comment"> * Passenger leaks memory.</span>
112
+ <a name="l00097"></a>00097 <span class="comment"> * - It would unnecessarily bloat the VM size of Apache worker processes.</span>
113
+ <a name="l00098"></a>00098 <span class="comment"> * - We had to resort to all kinds of tricks to make sure that fork()ing a process doesn't</span>
114
+ <a name="l00099"></a>00099 <span class="comment"> * result in file descriptor leaks.</span>
115
+ <a name="l00100"></a>00100 <span class="comment"> * - Despite everything, there was still a small chance that file descriptor leaks would</span>
116
+ <a name="l00101"></a>00101 <span class="comment"> * occur, and this could not be fixed. The reason for this is that the Apache control</span>
117
+ <a name="l00102"></a>00102 <span class="comment"> * process may call fork() right after the ApplicationPool server has established a new</span>
118
+ <a name="l00103"></a>00103 <span class="comment"> * connection with a client.</span>
119
+ <a name="l00104"></a>00104 <span class="comment"> *</span>
120
+ <a name="l00105"></a>00105 <span class="comment"> * Because of these problems, it was decided to split the ApplicationPool server to a</span>
121
+ <a name="l00106"></a>00106 <span class="comment"> * separate executable. This comes with no performance hit.</span>
122
+ <a name="l00107"></a>00107 <span class="comment"> *</span>
123
+ <a name="l00108"></a>00108 <span class="comment"> * &lt;h3&gt;Anonymous server socket&lt;/h3&gt;</span>
124
+ <a name="l00109"></a>00109 <span class="comment"> * Notice that ApplicationPoolServer does do not use TCP sockets at all, or even named Unix</span>
125
+ <a name="l00110"></a>00110 <span class="comment"> * sockets, despite being a server that can handle multiple clients! So ApplicationPoolServer</span>
126
+ <a name="l00111"></a>00111 <span class="comment"> * will expose no open ports or temporary Unix socket files. Only child processes are able</span>
127
+ <a name="l00112"></a>00112 <span class="comment"> * to use the ApplicationPoolServer.</span>
128
+ <a name="l00113"></a>00113 <span class="comment"> *</span>
129
+ <a name="l00114"></a>00114 <span class="comment"> * This is implemented through anonymous Unix sockets (&lt;tt&gt;socketpair()&lt;/tt&gt;) and file descriptor</span>
130
+ <a name="l00115"></a>00115 <span class="comment"> * passing. It allows one to emulate &lt;tt&gt;accept()&lt;/tt&gt;. ApplicationPoolServer is connected to</span>
131
+ <a name="l00116"></a>00116 <span class="comment"> * the server executable through a Unix socket pair. connect() sends a connect request to the</span>
132
+ <a name="l00117"></a>00117 <span class="comment"> * server through that socket. The server will then create a new socket pair, and pass one of</span>
133
+ <a name="l00118"></a>00118 <span class="comment"> * them back. This new socket pair represents the newly established connection.</span>
134
+ <a name="l00119"></a>00119 <span class="comment"> *</span>
135
+ <a name="l00120"></a>00120 <span class="comment"> * @ingroup Support</span>
136
+ <a name="l00121"></a>00121 <span class="comment"> */</span>
137
+ <a name="l00122"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html">00122</a> <span class="keyword">class </span><a class="code" href="classPassenger_1_1ApplicationPoolServer.html" title="Multi-process usage support for ApplicationPool.">ApplicationPoolServer</a> {
138
+ <a name="l00123"></a>00123 <span class="keyword">private</span>:<span class="comment"></span>
139
+ <a name="l00124"></a>00124 <span class="comment"> /**</span>
140
+ <a name="l00125"></a>00125 <span class="comment"> * Contains data shared between RemoteSession and Client.</span>
141
+ <a name="l00126"></a>00126 <span class="comment"> * Since RemoteSession and Client have different life times, i.e. one may be</span>
142
+ <a name="l00127"></a>00127 <span class="comment"> * destroyed before the other, they both use a smart pointer that points to</span>
143
+ <a name="l00128"></a>00128 <span class="comment"> * a SharedData. This way, the SharedData object is only destroyed when</span>
144
+ <a name="l00129"></a>00129 <span class="comment"> * both the RemoteSession and the Client object has been destroyed.</span>
145
+ <a name="l00130"></a>00130 <span class="comment"> */</span>
146
+ <a name="l00131"></a>00131 <span class="keyword">struct </span>SharedData {<span class="comment"></span>
147
+ <a name="l00132"></a>00132 <span class="comment"> /**</span>
148
+ <a name="l00133"></a>00133 <span class="comment"> * The socket connection to the ApplicationPool server, as was</span>
149
+ <a name="l00134"></a>00134 <span class="comment"> * established by ApplicationPoolServer::connect().</span>
150
+ <a name="l00135"></a>00135 <span class="comment"> */</span>
151
+ <a name="l00136"></a>00136 <span class="keywordtype">int</span> server;
152
+ <a name="l00137"></a>00137
153
+ <a name="l00138"></a>00138 ~SharedData() {
154
+ <a name="l00139"></a>00139 close(server);
155
+ <a name="l00140"></a>00140 }
156
+ <a name="l00141"></a>00141 };
157
+ <a name="l00142"></a>00142
158
+ <a name="l00143"></a>00143 <span class="keyword">typedef</span> shared_ptr&lt;SharedData&gt; SharedDataPtr;
159
+ <a name="l00144"></a>00144 <span class="comment"></span>
160
+ <a name="l00145"></a>00145 <span class="comment"> /**</span>
161
+ <a name="l00146"></a>00146 <span class="comment"> * An Application::Session which works together with ApplicationPoolServer.</span>
162
+ <a name="l00147"></a>00147 <span class="comment"> */</span>
163
+ <a name="l00148"></a>00148 <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 application instance.">Application</a>::Session {
164
+ <a name="l00149"></a>00149 <span class="keyword">private</span>:
165
+ <a name="l00150"></a>00150 SharedDataPtr data;
166
+ <a name="l00151"></a>00151 <span class="keywordtype">int</span> id;
167
+ <a name="l00152"></a>00152 <span class="keywordtype">int</span> reader;
168
+ <a name="l00153"></a>00153 <span class="keywordtype">int</span> writer;
169
+ <a name="l00154"></a>00154 pid_t pid;
170
+ <a name="l00155"></a>00155 <span class="keyword">public</span>:
171
+ <a name="l00156"></a>00156 RemoteSession(SharedDataPtr data, pid_t pid, <span class="keywordtype">int</span> <span class="keywordtype">id</span>, <span class="keywordtype">int</span> reader, <span class="keywordtype">int</span> writer) {
172
+ <a name="l00157"></a>00157 this-&gt;data = data;
173
+ <a name="l00158"></a>00158 this-&gt;pid = pid;
174
+ <a name="l00159"></a>00159 this-&gt;<span class="keywordtype">id</span> = id;
175
+ <a name="l00160"></a>00160 this-&gt;reader = reader;
176
+ <a name="l00161"></a>00161 this-&gt;writer = writer;
177
+ <a name="l00162"></a>00162 }
178
+ <a name="l00163"></a>00163
179
+ <a name="l00164"></a>00164 <span class="keyword">virtual</span> ~RemoteSession() {
180
+ <a name="l00165"></a>00165 closeReader();
181
+ <a name="l00166"></a>00166 closeWriter();
182
+ <a name="l00167"></a>00167 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a>(data-&gt;server).write(<span class="stringliteral">"close"</span>, <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(<span class="keywordtype">id</span>).c_str(), NULL);
183
+ <a name="l00168"></a>00168 }
184
+ <a name="l00169"></a>00169
185
+ <a name="l00170"></a>00170 <span class="keyword">virtual</span> <span class="keywordtype">int</span> getReader()<span class="keyword"> const </span>{
186
+ <a name="l00171"></a>00171 <span class="keywordflow">return</span> reader;
187
+ <a name="l00172"></a>00172 }
188
+ <a name="l00173"></a>00173
189
+ <a name="l00174"></a>00174 <span class="keyword">virtual</span> <span class="keywordtype">void</span> closeReader() {
190
+ <a name="l00175"></a>00175 <span class="keywordflow">if</span> (reader != -1) {
191
+ <a name="l00176"></a>00176 close(reader);
192
+ <a name="l00177"></a>00177 reader = -1;
193
+ <a name="l00178"></a>00178 }
194
+ <a name="l00179"></a>00179 }
195
+ <a name="l00180"></a>00180
196
+ <a name="l00181"></a>00181 <span class="keyword">virtual</span> <span class="keywordtype">int</span> getWriter()<span class="keyword"> const </span>{
197
+ <a name="l00182"></a>00182 <span class="keywordflow">return</span> writer;
198
+ <a name="l00183"></a>00183 }
199
+ <a name="l00184"></a>00184
200
+ <a name="l00185"></a>00185 <span class="keyword">virtual</span> <span class="keywordtype">void</span> closeWriter() {
201
+ <a name="l00186"></a>00186 <span class="keywordflow">if</span> (writer != -1) {
202
+ <a name="l00187"></a>00187 close(writer);
203
+ <a name="l00188"></a>00188 writer = -1;
204
+ <a name="l00189"></a>00189 }
205
+ <a name="l00190"></a>00190 }
206
+ <a name="l00191"></a>00191
207
+ <a name="l00192"></a>00192 <span class="keyword">virtual</span> pid_t getPid()<span class="keyword"> const </span>{
208
+ <a name="l00193"></a>00193 <span class="keywordflow">return</span> pid;
209
+ <a name="l00194"></a>00194 }
210
+ <a name="l00195"></a>00195 };
211
+ <a name="l00196"></a>00196 <span class="comment"></span>
212
+ <a name="l00197"></a>00197 <span class="comment"> /**</span>
213
+ <a name="l00198"></a>00198 <span class="comment"> * An ApplicationPool implementation that works together with ApplicationPoolServer.</span>
214
+ <a name="l00199"></a>00199 <span class="comment"> * It doesn't do much by itself, its job is mostly to forward queries/commands to</span>
215
+ <a name="l00200"></a>00200 <span class="comment"> * the server and returning the result. Most of the logic is in the server executable.</span>
216
+ <a name="l00201"></a>00201 <span class="comment"> */</span>
217
+ <a name="l00202"></a>00202 <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> {
218
+ <a name="l00203"></a>00203 <span class="keyword">private</span>:
219
+ <a name="l00204"></a>00204 SharedDataPtr data;
220
+ <a name="l00205"></a>00205
221
+ <a name="l00206"></a>00206 <span class="keyword">public</span>:<span class="comment"></span>
222
+ <a name="l00207"></a>00207 <span class="comment"> /**</span>
223
+ <a name="l00208"></a>00208 <span class="comment"> * Create a new Client.</span>
224
+ <a name="l00209"></a>00209 <span class="comment"> *</span>
225
+ <a name="l00210"></a>00210 <span class="comment"> * @param sock The newly established socket connection with the ApplicationPoolServer.</span>
226
+ <a name="l00211"></a>00211 <span class="comment"> */</span>
227
+ <a name="l00212"></a>00212 Client(<span class="keywordtype">int</span> sock) {
228
+ <a name="l00213"></a>00213 data = <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(<span class="keyword">new</span> SharedData());
229
+ <a name="l00214"></a>00214 data-&gt;server = sock;
230
+ <a name="l00215"></a>00215 }
231
+ <a name="l00216"></a>00216
232
+ <a name="l00217"></a>00217 <span class="keyword">virtual</span> <span class="keywordtype">void</span> clear() {
233
+ <a name="l00218"></a>00218 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
234
+ <a name="l00219"></a>00219 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);
235
+ <a name="l00220"></a>00220 }
236
+ <a name="l00221"></a>00221
237
+ <a name="l00222"></a>00222 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMaxIdleTime(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> seconds) {
238
+ <a name="l00223"></a>00223 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
239
+ <a name="l00224"></a>00224 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);
240
+ <a name="l00225"></a>00225 }
241
+ <a name="l00226"></a>00226
242
+ <a name="l00227"></a>00227 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMax(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> max) {
243
+ <a name="l00228"></a>00228 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
244
+ <a name="l00229"></a>00229 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);
245
+ <a name="l00230"></a>00230 }
246
+ <a name="l00231"></a>00231
247
+ <a name="l00232"></a>00232 <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> getActive()<span class="keyword"> const </span>{
248
+ <a name="l00233"></a>00233 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
249
+ <a name="l00234"></a>00234 vector&lt;string&gt; args;
250
+ <a name="l00235"></a>00235
251
+ <a name="l00236"></a>00236 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);
252
+ <a name="l00237"></a>00237 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args);
253
+ <a name="l00238"></a>00238 <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());
254
+ <a name="l00239"></a>00239 }
255
+ <a name="l00240"></a>00240
256
+ <a name="l00241"></a>00241 <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> getCount()<span class="keyword"> const </span>{
257
+ <a name="l00242"></a>00242 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
258
+ <a name="l00243"></a>00243 vector&lt;string&gt; args;
259
+ <a name="l00244"></a>00244
260
+ <a name="l00245"></a>00245 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);
261
+ <a name="l00246"></a>00246 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args);
262
+ <a name="l00247"></a>00247 <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());
263
+ <a name="l00248"></a>00248 }
264
+ <a name="l00249"></a>00249
265
+ <a name="l00250"></a>00250 <span class="keyword">virtual</span> pid_t getSpawnServerPid()<span class="keyword"> const </span>{
266
+ <a name="l00251"></a>00251 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
267
+ <a name="l00252"></a>00252 vector&lt;string&gt; args;
268
+ <a name="l00253"></a>00253
269
+ <a name="l00254"></a>00254 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);
270
+ <a name="l00255"></a>00255 channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args);
271
+ <a name="l00256"></a>00256 <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());
272
+ <a name="l00257"></a>00257 }
273
+ <a name="l00258"></a>00258
274
+ <a name="l00259"></a>00259 <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>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot, <span class="keywordtype">bool</span> lowerPrivilege = <span class="keyword">true</span>,
275
+ <a name="l00260"></a>00260 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;lowestUser = <span class="stringliteral">"nobody"</span>) {
276
+ <a name="l00261"></a>00261 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(data-&gt;server);
277
+ <a name="l00262"></a>00262 vector&lt;string&gt; args;
278
+ <a name="l00263"></a>00263 <span class="keywordtype">int</span> reader, writer;
279
+ <a name="l00264"></a>00264
280
+ <a name="l00265"></a>00265 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(),
281
+ <a name="l00266"></a>00266 (lowerPrivilege) ? <span class="stringliteral">"true"</span> : <span class="stringliteral">"false"</span>,
282
+ <a name="l00267"></a>00267 lowestUser.c_str(), NULL);
283
+ <a name="l00268"></a>00268 <span class="keywordflow">if</span> (!channel.<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args)) {
284
+ <a name="l00269"></a>00269 <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 closed the connection."</span>);
285
+ <a name="l00270"></a>00270 }
286
+ <a name="l00271"></a>00271 <span class="keywordflow">if</span> (args[0] == <span class="stringliteral">"ok"</span>) {
287
+ <a name="l00272"></a>00272 reader = 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>();
288
+ <a name="l00273"></a>00273 writer = 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>();
289
+ <a name="l00274"></a>00274 <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(data, <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]), reader, writer));
290
+ <a name="l00275"></a>00275 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (args[0] == <span class="stringliteral">"SpawnException"</span>) {
291
+ <a name="l00276"></a>00276 <span class="keywordflow">if</span> (args[2] == <span class="stringliteral">"true"</span>) {
292
+ <a name="l00277"></a>00277 <span class="keywordtype">string</span> errorPage;
293
+ <a name="l00278"></a>00278
294
+ <a name="l00279"></a>00279 <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)) {
295
+ <a name="l00280"></a>00280 <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 closed the connection."</span>);
296
+ <a name="l00281"></a>00281 }
297
+ <a name="l00282"></a>00282 <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);
298
+ <a name="l00283"></a>00283 } <span class="keywordflow">else</span> {
299
+ <a name="l00284"></a>00284 <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]);
300
+ <a name="l00285"></a>00285 }
301
+ <a name="l00286"></a>00286 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (args[0] == <span class="stringliteral">"IOException"</span>) {
302
+ <a name="l00287"></a>00287 <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]);
303
+ <a name="l00288"></a>00288 } <span class="keywordflow">else</span> {
304
+ <a name="l00289"></a>00289 <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 an unknown message."</span>);
305
+ <a name="l00290"></a>00290 }
306
+ <a name="l00291"></a>00291 }
307
+ <a name="l00292"></a>00292 };
308
308
  <a name="l00293"></a>00293
309
- <a name="l00294"></a>00294 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> SERVER_SOCKET_FD = 3;
310
- <a name="l00295"></a>00295
311
- <a name="l00296"></a>00296 <span class="keywordtype">string</span> m_serverExecutable;
312
- <a name="l00297"></a>00297 <span class="keywordtype">string</span> m_spawnServerCommand;
313
- <a name="l00298"></a>00298 <span class="keywordtype">string</span> m_logFile;
314
- <a name="l00299"></a>00299 <span class="keywordtype">string</span> m_environment;
315
- <a name="l00300"></a>00300 <span class="keywordtype">string</span> m_rubyCommand;
316
- <a name="l00301"></a>00301 <span class="keywordtype">string</span> m_user;
317
- <a name="l00302"></a>00302 <span class="comment"></span>
318
- <a name="l00303"></a>00303 <span class="comment"> /**</span>
319
- <a name="l00304"></a>00304 <span class="comment"> * The PID of the ApplicationPool server process. If no server process</span>
320
- <a name="l00305"></a>00305 <span class="comment"> * is running, then &lt;tt&gt;serverPid == 0&lt;/tt&gt;.</span>
321
- <a name="l00306"></a>00306 <span class="comment"> *</span>
322
- <a name="l00307"></a>00307 <span class="comment"> * @invariant</span>
323
- <a name="l00308"></a>00308 <span class="comment"> * if serverPid == 0:</span>
324
- <a name="l00309"></a>00309 <span class="comment"> * serverSocket == -1</span>
325
- <a name="l00310"></a>00310 <span class="comment"> */</span>
326
- <a name="l00311"></a>00311 pid_t serverPid;
327
- <a name="l00312"></a>00312 <span class="comment"></span>
328
- <a name="l00313"></a>00313 <span class="comment"> /**</span>
329
- <a name="l00314"></a>00314 <span class="comment"> * The connection to the ApplicationPool server process. If no server</span>
330
- <a name="l00315"></a>00315 <span class="comment"> * process is running, then &lt;tt&gt;serverSocket == -1&lt;/tt&gt;.</span>
331
- <a name="l00316"></a>00316 <span class="comment"> *</span>
332
- <a name="l00317"></a>00317 <span class="comment"> * @invariant</span>
333
- <a name="l00318"></a>00318 <span class="comment"> * if serverPid == 0:</span>
334
- <a name="l00319"></a>00319 <span class="comment"> * serverSocket == -1</span>
335
- <a name="l00320"></a>00320 <span class="comment"> */</span>
336
- <a name="l00321"></a>00321 <span class="keywordtype">int</span> serverSocket;
337
- <a name="l00322"></a>00322 <span class="comment"></span>
338
- <a name="l00323"></a>00323 <span class="comment"> /**</span>
339
- <a name="l00324"></a>00324 <span class="comment"> * Shutdown the currently running ApplicationPool server process.</span>
340
- <a name="l00325"></a>00325 <span class="comment"> *</span>
341
- <a name="l00326"></a>00326 <span class="comment"> * @pre serverSocket != -1 &amp;&amp; serverPid != 0</span>
342
- <a name="l00327"></a>00327 <span class="comment"> * @post serverSocket == -1 &amp;&amp; serverPid == 0</span>
343
- <a name="l00328"></a>00328 <span class="comment"> */</span>
344
- <a name="l00329"></a>00329 <span class="keywordtype">void</span> shutdownServer() {
345
- <a name="l00330"></a>00330 time_t begin;
346
- <a name="l00331"></a>00331 <span class="keywordtype">bool</span> done;
347
- <a name="l00332"></a>00332 <span class="keywordtype">int</span> ret;
348
- <a name="l00333"></a>00333
349
- <a name="l00334"></a>00334 <span class="keywordflow">do</span> {
350
- <a name="l00335"></a>00335 ret = close(serverSocket);
351
- <a name="l00336"></a>00336 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; errno == EINTR);
352
- <a name="l00337"></a>00337
353
- <a name="l00338"></a>00338 P_DEBUG(<span class="stringliteral">"Waiting for existing ApplicationPoolServerExecutable to exit..."</span>);
354
- <a name="l00339"></a>00339 begin = time(NULL);
355
- <a name="l00340"></a>00340 <span class="keywordflow">while</span> (!done &amp;&amp; time(NULL) &lt; begin + 5) {
356
- <a name="l00341"></a>00341 done = waitpid(serverPid, NULL, WNOHANG) &gt; 0;
357
- <a name="l00342"></a>00342 usleep(100000);
358
- <a name="l00343"></a>00343 }
359
- <a name="l00344"></a>00344 <span class="keywordflow">if</span> (done) {
360
- <a name="l00345"></a>00345 P_DEBUG(<span class="stringliteral">"ApplicationPoolServerExecutable exited."</span>);
361
- <a name="l00346"></a>00346 } <span class="keywordflow">else</span> {
362
- <a name="l00347"></a>00347 P_DEBUG(<span class="stringliteral">"ApplicationPoolServerExecutable not exited in time. Killing it..."</span>);
363
- <a name="l00348"></a>00348 kill(serverPid, SIGTERM);
364
- <a name="l00349"></a>00349 waitpid(serverPid, NULL, 0);
365
- <a name="l00350"></a>00350 }
366
- <a name="l00351"></a>00351 serverSocket = -1;
367
- <a name="l00352"></a>00352 serverPid = 0;
368
- <a name="l00353"></a>00353 }
369
- <a name="l00354"></a>00354 <span class="comment"></span>
370
- <a name="l00355"></a>00355 <span class="comment"> /**</span>
371
- <a name="l00356"></a>00356 <span class="comment"> * Start an ApplicationPool server process. If there's already one running,</span>
372
- <a name="l00357"></a>00357 <span class="comment"> * then the currently running one will be shutdown.</span>
373
- <a name="l00358"></a>00358 <span class="comment"> *</span>
374
- <a name="l00359"></a>00359 <span class="comment"> * @post serverSocket != -1 &amp;&amp; serverPid != 0</span>
375
- <a name="l00360"></a>00360 <span class="comment"> * @throw SystemException Something went wrong.</span>
376
- <a name="l00361"></a>00361 <span class="comment"> */</span>
377
- <a name="l00362"></a>00362 <span class="keywordtype">void</span> restartServer() {
378
- <a name="l00363"></a>00363 <span class="keywordtype">int</span> fds[2];
379
- <a name="l00364"></a>00364 pid_t pid;
380
- <a name="l00365"></a>00365
381
- <a name="l00366"></a>00366 <span class="keywordflow">if</span> (serverPid != 0) {
382
- <a name="l00367"></a>00367 shutdownServer();
383
- <a name="l00368"></a>00368 }
384
- <a name="l00369"></a>00369
385
- <a name="l00370"></a>00370 <span class="keywordflow">if</span> (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) {
386
- <a name="l00371"></a>00371 <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);
387
- <a name="l00372"></a>00372 }
388
- <a name="l00373"></a>00373
389
- <a name="l00374"></a>00374 pid = fork();
390
- <a name="l00375"></a>00375 <span class="keywordflow">if</span> (pid == 0) { <span class="comment">// Child process.</span>
391
- <a name="l00376"></a>00376 dup2(fds[0], 3);
392
- <a name="l00377"></a>00377
393
- <a name="l00378"></a>00378 <span class="comment">// Close all unnecessary file descriptors</span>
394
- <a name="l00379"></a>00379 <span class="keywordflow">for</span> (<span class="keywordtype">long</span> i = sysconf(_SC_OPEN_MAX) - 1; i &gt; SERVER_SOCKET_FD; i--) {
395
- <a name="l00380"></a>00380 close(i);
396
- <a name="l00381"></a>00381 }
397
- <a name="l00382"></a>00382
398
- <a name="l00383"></a>00383 execlp(
399
- <a name="l00384"></a>00384 #<span class="keywordflow">if</span> 0
400
- <a name="l00385"></a>00385 <span class="stringliteral">"valgrind"</span>,
309
+ <a name="l00294"></a>00294
310
+ <a name="l00295"></a>00295 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> SERVER_SOCKET_FD = 3;
311
+ <a name="l00296"></a>00296
312
+ <a name="l00297"></a>00297 <span class="keywordtype">string</span> m_serverExecutable;
313
+ <a name="l00298"></a>00298 <span class="keywordtype">string</span> m_spawnServerCommand;
314
+ <a name="l00299"></a>00299 <span class="keywordtype">string</span> m_logFile;
315
+ <a name="l00300"></a>00300 <span class="keywordtype">string</span> m_environment;
316
+ <a name="l00301"></a>00301 <span class="keywordtype">string</span> m_rubyCommand;
317
+ <a name="l00302"></a>00302 <span class="keywordtype">string</span> m_user;
318
+ <a name="l00303"></a>00303 <span class="comment"></span>
319
+ <a name="l00304"></a>00304 <span class="comment"> /**</span>
320
+ <a name="l00305"></a>00305 <span class="comment"> * The PID of the ApplicationPool server process. If no server process</span>
321
+ <a name="l00306"></a>00306 <span class="comment"> * is running, then &lt;tt&gt;serverPid == 0&lt;/tt&gt;.</span>
322
+ <a name="l00307"></a>00307 <span class="comment"> *</span>
323
+ <a name="l00308"></a>00308 <span class="comment"> * @invariant</span>
324
+ <a name="l00309"></a>00309 <span class="comment"> * if serverPid == 0:</span>
325
+ <a name="l00310"></a>00310 <span class="comment"> * serverSocket == -1</span>
326
+ <a name="l00311"></a>00311 <span class="comment"> */</span>
327
+ <a name="l00312"></a>00312 pid_t serverPid;
328
+ <a name="l00313"></a>00313 <span class="comment"></span>
329
+ <a name="l00314"></a>00314 <span class="comment"> /**</span>
330
+ <a name="l00315"></a>00315 <span class="comment"> * The connection to the ApplicationPool server process. If no server</span>
331
+ <a name="l00316"></a>00316 <span class="comment"> * process is running, then &lt;tt&gt;serverSocket == -1&lt;/tt&gt;.</span>
332
+ <a name="l00317"></a>00317 <span class="comment"> *</span>
333
+ <a name="l00318"></a>00318 <span class="comment"> * @invariant</span>
334
+ <a name="l00319"></a>00319 <span class="comment"> * if serverPid == 0:</span>
335
+ <a name="l00320"></a>00320 <span class="comment"> * serverSocket == -1</span>
336
+ <a name="l00321"></a>00321 <span class="comment"> */</span>
337
+ <a name="l00322"></a>00322 <span class="keywordtype">int</span> serverSocket;
338
+ <a name="l00323"></a>00323 <span class="comment"></span>
339
+ <a name="l00324"></a>00324 <span class="comment"> /**</span>
340
+ <a name="l00325"></a>00325 <span class="comment"> * Shutdown the currently running ApplicationPool server process.</span>
341
+ <a name="l00326"></a>00326 <span class="comment"> *</span>
342
+ <a name="l00327"></a>00327 <span class="comment"> * @pre serverSocket != -1 &amp;&amp; serverPid != 0</span>
343
+ <a name="l00328"></a>00328 <span class="comment"> * @post serverSocket == -1 &amp;&amp; serverPid == 0</span>
344
+ <a name="l00329"></a>00329 <span class="comment"> */</span>
345
+ <a name="l00330"></a>00330 <span class="keywordtype">void</span> shutdownServer() {
346
+ <a name="l00331"></a>00331 time_t begin;
347
+ <a name="l00332"></a>00332 <span class="keywordtype">bool</span> done;
348
+ <a name="l00333"></a>00333 <span class="keywordtype">int</span> ret;
349
+ <a name="l00334"></a>00334
350
+ <a name="l00335"></a>00335 <span class="keywordflow">do</span> {
351
+ <a name="l00336"></a>00336 ret = close(serverSocket);
352
+ <a name="l00337"></a>00337 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; errno == EINTR);
353
+ <a name="l00338"></a>00338
354
+ <a name="l00339"></a>00339 P_DEBUG(<span class="stringliteral">"Waiting for existing ApplicationPoolServerExecutable to exit..."</span>);
355
+ <a name="l00340"></a>00340 begin = time(NULL);
356
+ <a name="l00341"></a>00341 <span class="keywordflow">while</span> (!done &amp;&amp; time(NULL) &lt; begin + 5) {
357
+ <a name="l00342"></a>00342 done = waitpid(serverPid, NULL, WNOHANG) &gt; 0;
358
+ <a name="l00343"></a>00343 usleep(100000);
359
+ <a name="l00344"></a>00344 }
360
+ <a name="l00345"></a>00345 <span class="keywordflow">if</span> (done) {
361
+ <a name="l00346"></a>00346 P_DEBUG(<span class="stringliteral">"ApplicationPoolServerExecutable exited."</span>);
362
+ <a name="l00347"></a>00347 } <span class="keywordflow">else</span> {
363
+ <a name="l00348"></a>00348 P_DEBUG(<span class="stringliteral">"ApplicationPoolServerExecutable not exited in time. Killing it..."</span>);
364
+ <a name="l00349"></a>00349 kill(serverPid, SIGTERM);
365
+ <a name="l00350"></a>00350 waitpid(serverPid, NULL, 0);
366
+ <a name="l00351"></a>00351 }
367
+ <a name="l00352"></a>00352 serverSocket = -1;
368
+ <a name="l00353"></a>00353 serverPid = 0;
369
+ <a name="l00354"></a>00354 }
370
+ <a name="l00355"></a>00355 <span class="comment"></span>
371
+ <a name="l00356"></a>00356 <span class="comment"> /**</span>
372
+ <a name="l00357"></a>00357 <span class="comment"> * Start an ApplicationPool server process. If there's already one running,</span>
373
+ <a name="l00358"></a>00358 <span class="comment"> * then the currently running one will be shutdown.</span>
374
+ <a name="l00359"></a>00359 <span class="comment"> *</span>
375
+ <a name="l00360"></a>00360 <span class="comment"> * @post serverSocket != -1 &amp;&amp; serverPid != 0</span>
376
+ <a name="l00361"></a>00361 <span class="comment"> * @throw SystemException Something went wrong.</span>
377
+ <a name="l00362"></a>00362 <span class="comment"> */</span>
378
+ <a name="l00363"></a>00363 <span class="keywordtype">void</span> restartServer() {
379
+ <a name="l00364"></a>00364 <span class="keywordtype">int</span> fds[2];
380
+ <a name="l00365"></a>00365 pid_t pid;
381
+ <a name="l00366"></a>00366
382
+ <a name="l00367"></a>00367 <span class="keywordflow">if</span> (serverPid != 0) {
383
+ <a name="l00368"></a>00368 shutdownServer();
384
+ <a name="l00369"></a>00369 }
385
+ <a name="l00370"></a>00370
386
+ <a name="l00371"></a>00371 <span class="keywordflow">if</span> (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) {
387
+ <a name="l00372"></a>00372 <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);
388
+ <a name="l00373"></a>00373 }
389
+ <a name="l00374"></a>00374
390
+ <a name="l00375"></a>00375 pid = fork();
391
+ <a name="l00376"></a>00376 <span class="keywordflow">if</span> (pid == 0) { <span class="comment">// Child process.</span>
392
+ <a name="l00377"></a>00377 dup2(fds[0], 3);
393
+ <a name="l00378"></a>00378
394
+ <a name="l00379"></a>00379 <span class="comment">// Close all unnecessary file descriptors</span>
395
+ <a name="l00380"></a>00380 <span class="keywordflow">for</span> (<span class="keywordtype">long</span> i = sysconf(_SC_OPEN_MAX) - 1; i &gt; SERVER_SOCKET_FD; i--) {
396
+ <a name="l00381"></a>00381 close(i);
397
+ <a name="l00382"></a>00382 }
398
+ <a name="l00383"></a>00383
399
+ <a name="l00384"></a>00384 execlp(
400
+ <a name="l00385"></a>00385 #<span class="keywordflow">if</span> 0
401
401
  <a name="l00386"></a>00386 <span class="stringliteral">"valgrind"</span>,
402
- <a name="l00387"></a>00387 #<span class="keywordflow">else</span>
403
- <a name="l00388"></a>00388 m_serverExecutable.c_str(),
404
- <a name="l00389"></a>00389 <span class="preprocessor"> #endif</span>
405
- <a name="l00390"></a>00390 <span class="preprocessor"></span> m_serverExecutable.c_str(),
406
- <a name="l00391"></a>00391 m_spawnServerCommand.c_str(),
407
- <a name="l00392"></a>00392 m_logFile.c_str(),
408
- <a name="l00393"></a>00393 m_environment.c_str(),
409
- <a name="l00394"></a>00394 m_rubyCommand.c_str(),
410
- <a name="l00395"></a>00395 m_user.c_str(),
411
- <a name="l00396"></a>00396 NULL);
412
- <a name="l00397"></a>00397 <span class="keywordtype">int</span> e = errno;
413
- <a name="l00398"></a>00398 fprintf(stderr, <span class="stringliteral">"*** Passenger ERROR: Cannot execute %s: %s (%d)\n"</span>,
414
- <a name="l00399"></a>00399 m_serverExecutable.c_str(), strerror(e), e);
415
- <a name="l00400"></a>00400 fflush(stderr);
416
- <a name="l00401"></a>00401 _exit(1);
417
- <a name="l00402"></a>00402 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pid == -1) { <span class="comment">// Error.</span>
418
- <a name="l00403"></a>00403 close(fds[0]);
419
- <a name="l00404"></a>00404 close(fds[1]);
420
- <a name="l00405"></a>00405 <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);
421
- <a name="l00406"></a>00406 } <span class="keywordflow">else</span> { <span class="comment">// Parent process.</span>
422
- <a name="l00407"></a>00407 close(fds[0]);
423
- <a name="l00408"></a>00408 serverSocket = fds[1];
424
- <a name="l00409"></a>00409 serverPid = pid;
425
- <a name="l00410"></a>00410 }
426
- <a name="l00411"></a>00411 }
427
- <a name="l00412"></a>00412
428
- <a name="l00413"></a>00413 <span class="keyword">public</span>:<span class="comment"></span>
429
- <a name="l00414"></a>00414 <span class="comment"> /**</span>
430
- <a name="l00415"></a>00415 <span class="comment"> * Create a new ApplicationPoolServer object.</span>
431
- <a name="l00416"></a>00416 <span class="comment"> *</span>
432
- <a name="l00417"></a>00417 <span class="comment"> * @param serverExecutable The filename of the ApplicationPool server</span>
433
- <a name="l00418"></a>00418 <span class="comment"> * executable to use.</span>
434
- <a name="l00419"></a>00419 <span class="comment"> * @param spawnServerCommand The filename of the spawn server to use.</span>
435
- <a name="l00420"></a>00420 <span class="comment"> * @param logFile Specify a log file that the spawn server should use.</span>
436
- <a name="l00421"></a>00421 <span class="comment"> * Messages on its standard output and standard error channels</span>
437
- <a name="l00422"></a>00422 <span class="comment"> * will be written to this log file. If an empty string is</span>
438
- <a name="l00423"></a>00423 <span class="comment"> * specified, no log file will be used, and the spawn server</span>
439
- <a name="l00424"></a>00424 <span class="comment"> * will use the same standard output/error channels as the</span>
440
- <a name="l00425"></a>00425 <span class="comment"> * current process.</span>
441
- <a name="l00426"></a>00426 <span class="comment"> * @param environment The RAILS_ENV environment that all RoR applications</span>
442
- <a name="l00427"></a>00427 <span class="comment"> * should use. If an empty string is specified, the current value</span>
443
- <a name="l00428"></a>00428 <span class="comment"> * of the RAILS_ENV environment variable will be used.</span>
444
- <a name="l00429"></a>00429 <span class="comment"> * @param rubyCommand The Ruby interpreter's command.</span>
445
- <a name="l00430"></a>00430 <span class="comment"> * @param user The user that the spawn manager should run as. This</span>
446
- <a name="l00431"></a>00431 <span class="comment"> * parameter only has effect if the current process is</span>
447
- <a name="l00432"></a>00432 <span class="comment"> * running as root. If the empty string is given, or if</span>
448
- <a name="l00433"></a>00433 <span class="comment"> * the &lt;tt&gt;user&lt;/tt&gt; is not a valid username, then</span>
449
- <a name="l00434"></a>00434 <span class="comment"> * the spawn manager will be run as the current user.</span>
450
- <a name="l00435"></a>00435 <span class="comment"> * @throws SystemException An error occured while trying to setup the spawn server</span>
451
- <a name="l00436"></a>00436 <span class="comment"> * or the server socket.</span>
452
- <a name="l00437"></a>00437 <span class="comment"> * @throws IOException The specified log file could not be opened.</span>
453
- <a name="l00438"></a>00438 <span class="comment"> */</span>
454
- <a name="l00439"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html#3b63e995b09857659935132b6a4b97cc">00439</a> <a class="code" href="classPassenger_1_1ApplicationPoolServer.html#3b63e995b09857659935132b6a4b97cc" title="Create a new ApplicationPoolServer object.">ApplicationPoolServer</a>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;serverExecutable,
455
- <a name="l00440"></a>00440 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;spawnServerCommand,
456
- <a name="l00441"></a>00441 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;logFile = <span class="stringliteral">""</span>,
457
- <a name="l00442"></a>00442 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;environment = <span class="stringliteral">"production"</span>,
458
- <a name="l00443"></a>00443 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;rubyCommand = <span class="stringliteral">"ruby"</span>,
459
- <a name="l00444"></a>00444 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;user = <span class="stringliteral">""</span>)
460
- <a name="l00445"></a>00445 : m_serverExecutable(serverExecutable),
461
- <a name="l00446"></a>00446 m_spawnServerCommand(spawnServerCommand),
462
- <a name="l00447"></a>00447 m_logFile(logFile),
463
- <a name="l00448"></a>00448 m_environment(environment),
464
- <a name="l00449"></a>00449 m_rubyCommand(rubyCommand),
465
- <a name="l00450"></a>00450 m_user(user) {
466
- <a name="l00451"></a>00451 serverSocket = -1;
467
- <a name="l00452"></a>00452 serverPid = 0;
468
- <a name="l00453"></a>00453 restartServer();
469
- <a name="l00454"></a>00454 }
470
- <a name="l00455"></a>00455
471
- <a name="l00456"></a>00456 ~<a class="code" href="classPassenger_1_1ApplicationPoolServer.html" title="Multi-process usage support for ApplicationPool.">ApplicationPoolServer</a>() {
472
- <a name="l00457"></a>00457 <span class="keywordflow">if</span> (serverSocket != -1) {
473
- <a name="l00458"></a>00458 shutdownServer();
474
- <a name="l00459"></a>00459 }
475
- <a name="l00460"></a>00460 }
476
- <a name="l00461"></a>00461 <span class="comment"></span>
477
- <a name="l00462"></a>00462 <span class="comment"> /**</span>
478
- <a name="l00463"></a>00463 <span class="comment"> * Connects to the server and returns a usable ApplicationPool object.</span>
479
- <a name="l00464"></a>00464 <span class="comment"> * All cache/pool data of this ApplicationPool is actually stored on</span>
480
- <a name="l00465"></a>00465 <span class="comment"> * the server and shared with other clients, but that is totally</span>
481
- <a name="l00466"></a>00466 <span class="comment"> * transparent to the user of the ApplicationPool object.</span>
482
- <a name="l00467"></a>00467 <span class="comment"> *</span>
483
- <a name="l00468"></a>00468 <span class="comment"> * @warning</span>
484
- <a name="l00469"></a>00469 <span class="comment"> * One may only use the returned ApplicationPool object for handling</span>
485
- <a name="l00470"></a>00470 <span class="comment"> * one session at a time. For example, don't do stuff like this:</span>
486
- <a name="l00471"></a>00471 <span class="comment"> * @code</span>
487
- <a name="l00472"></a>00472 <span class="comment"> * ApplicationPoolPtr pool = server.connect();</span>
488
- <a name="l00473"></a>00473 <span class="comment"> * Application::SessionPtr session1 = pool-&gt;get(...);</span>
489
- <a name="l00474"></a>00474 <span class="comment"> * Application::SessionPtr session2 = pool-&gt;get(...);</span>
490
- <a name="l00475"></a>00475 <span class="comment"> * @endcode</span>
491
- <a name="l00476"></a>00476 <span class="comment"> * Otherwise, a deadlock can occur under certain circumstances.</span>
492
- <a name="l00477"></a>00477 <span class="comment"> * @warning</span>
493
- <a name="l00478"></a>00478 <span class="comment"> * Instead, one should call connect() multiple times:</span>
494
- <a name="l00479"></a>00479 <span class="comment"> * @code</span>
495
- <a name="l00480"></a>00480 <span class="comment"> * ApplicationPoolPtr pool1 = server.connect();</span>
496
- <a name="l00481"></a>00481 <span class="comment"> * Application::SessionPtr session1 = pool1-&gt;get(...);</span>
497
- <a name="l00482"></a>00482 <span class="comment"> * </span>
498
- <a name="l00483"></a>00483 <span class="comment"> * ApplicationPoolPtr pool2 = server.connect();</span>
499
- <a name="l00484"></a>00484 <span class="comment"> * Application::SessionPtr session2 = pool2-&gt;get(...);</span>
500
- <a name="l00485"></a>00485 <span class="comment"> * @endcode</span>
501
- <a name="l00486"></a>00486 <span class="comment"> *</span>
502
- <a name="l00487"></a>00487 <span class="comment"> * @throws SystemException Something went wrong.</span>
503
- <a name="l00488"></a>00488 <span class="comment"> * @throws IOException Something went wrong.</span>
504
- <a name="l00489"></a>00489 <span class="comment"> */</span>
505
- <a name="l00490"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html#18f77057cc28e7924a8f4d1397aa0468">00490</a> ApplicationPoolPtr <a class="code" href="classPassenger_1_1ApplicationPoolServer.html#18f77057cc28e7924a8f4d1397aa0468" title="Connects to the server and returns a usable ApplicationPool object.">connect</a>() {
506
- <a name="l00491"></a>00491 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(serverSocket);
507
- <a name="l00492"></a>00492 <span class="keywordtype">int</span> clientConnection;
508
- <a name="l00493"></a>00493
509
- <a name="l00494"></a>00494 <span class="comment">// Write some random data to wake up the server.</span>
510
- <a name="l00495"></a>00495 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);
511
- <a name="l00496"></a>00496
512
- <a name="l00497"></a>00497 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>();
513
- <a name="l00498"></a>00498 <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));
514
- <a name="l00499"></a>00499 }
515
- <a name="l00500"></a>00500 <span class="comment"></span>
516
- <a name="l00501"></a>00501 <span class="comment"> /**</span>
517
- <a name="l00502"></a>00502 <span class="comment"> * Detach the server, thereby telling it that we don't want to connect</span>
518
- <a name="l00503"></a>00503 <span class="comment"> * to it anymore. This frees up some resources in the current process,</span>
519
- <a name="l00504"></a>00504 <span class="comment"> * such as file descriptors.</span>
520
- <a name="l00505"></a>00505 <span class="comment"> *</span>
521
- <a name="l00506"></a>00506 <span class="comment"> * This method is particularily useful to Apache worker processes that</span>
522
- <a name="l00507"></a>00507 <span class="comment"> * have just established a connection with the ApplicationPool server.</span>
523
- <a name="l00508"></a>00508 <span class="comment"> * Any sessions that are opened prior to calling detach(), will keep</span>
524
- <a name="l00509"></a>00509 <span class="comment"> * working even after a detach().</span>
525
- <a name="l00510"></a>00510 <span class="comment"> *</span>
526
- <a name="l00511"></a>00511 <span class="comment"> * This method may only be called once. The ApplicationPoolServer object</span>
527
- <a name="l00512"></a>00512 <span class="comment"> * will become unusable once detach() has been called, so call connect()</span>
528
- <a name="l00513"></a>00513 <span class="comment"> * before calling detach().</span>
529
- <a name="l00514"></a>00514 <span class="comment"> */</span>
530
- <a name="l00515"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html#b13957e32ae8ca36ba85f2e6ffefd5ce">00515</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1ApplicationPoolServer.html#b13957e32ae8ca36ba85f2e6ffefd5ce" title="Detach the server, thereby telling it that we don&amp;#39;t want to connect to it anymore...">detach</a>() {
531
- <a name="l00516"></a>00516 close(serverSocket);
532
- <a name="l00517"></a>00517 serverSocket = -1;
533
- <a name="l00518"></a>00518 }
534
- <a name="l00519"></a>00519 };
535
- <a name="l00520"></a>00520
536
- <a name="l00521"></a>00521 <span class="keyword">typedef</span> shared_ptr&lt;ApplicationPoolServer&gt; ApplicationPoolServerPtr;
537
- <a name="l00522"></a>00522
538
- <a name="l00523"></a>00523 } <span class="comment">// namespace Passenger</span>
539
- <a name="l00524"></a>00524
540
- <a name="l00525"></a>00525 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_APPLICATION_POOL_SERVER_H_ */</span>
541
- </pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Mon Apr 28 11:08:59 2008 for Passenger by&nbsp;
402
+ <a name="l00387"></a>00387 <span class="stringliteral">"valgrind"</span>,
403
+ <a name="l00388"></a>00388 #<span class="keywordflow">else</span>
404
+ <a name="l00389"></a>00389 m_serverExecutable.c_str(),
405
+ <a name="l00390"></a>00390 <span class="preprocessor"> #endif</span>
406
+ <a name="l00391"></a>00391 <span class="preprocessor"></span> m_serverExecutable.c_str(),
407
+ <a name="l00392"></a>00392 m_spawnServerCommand.c_str(),
408
+ <a name="l00393"></a>00393 m_logFile.c_str(),
409
+ <a name="l00394"></a>00394 m_environment.c_str(),
410
+ <a name="l00395"></a>00395 m_rubyCommand.c_str(),
411
+ <a name="l00396"></a>00396 m_user.c_str(),
412
+ <a name="l00397"></a>00397 NULL);
413
+ <a name="l00398"></a>00398 <span class="keywordtype">int</span> e = errno;
414
+ <a name="l00399"></a>00399 fprintf(stderr, <span class="stringliteral">"*** Passenger ERROR: Cannot execute %s: %s (%d)\n"</span>,
415
+ <a name="l00400"></a>00400 m_serverExecutable.c_str(), strerror(e), e);
416
+ <a name="l00401"></a>00401 fflush(stderr);
417
+ <a name="l00402"></a>00402 _exit(1);
418
+ <a name="l00403"></a>00403 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pid == -1) { <span class="comment">// Error.</span>
419
+ <a name="l00404"></a>00404 close(fds[0]);
420
+ <a name="l00405"></a>00405 close(fds[1]);
421
+ <a name="l00406"></a>00406 <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);
422
+ <a name="l00407"></a>00407 } <span class="keywordflow">else</span> { <span class="comment">// Parent process.</span>
423
+ <a name="l00408"></a>00408 close(fds[0]);
424
+ <a name="l00409"></a>00409 serverSocket = fds[1];
425
+ <a name="l00410"></a>00410 serverPid = pid;
426
+ <a name="l00411"></a>00411 }
427
+ <a name="l00412"></a>00412 }
428
+ <a name="l00413"></a>00413
429
+ <a name="l00414"></a>00414 <span class="keyword">public</span>:<span class="comment"></span>
430
+ <a name="l00415"></a>00415 <span class="comment"> /**</span>
431
+ <a name="l00416"></a>00416 <span class="comment"> * Create a new ApplicationPoolServer object.</span>
432
+ <a name="l00417"></a>00417 <span class="comment"> *</span>
433
+ <a name="l00418"></a>00418 <span class="comment"> * @param serverExecutable The filename of the ApplicationPool server</span>
434
+ <a name="l00419"></a>00419 <span class="comment"> * executable to use.</span>
435
+ <a name="l00420"></a>00420 <span class="comment"> * @param spawnServerCommand The filename of the spawn server to use.</span>
436
+ <a name="l00421"></a>00421 <span class="comment"> * @param logFile Specify a log file that the spawn server should use.</span>
437
+ <a name="l00422"></a>00422 <span class="comment"> * Messages on its standard output and standard error channels</span>
438
+ <a name="l00423"></a>00423 <span class="comment"> * will be written to this log file. If an empty string is</span>
439
+ <a name="l00424"></a>00424 <span class="comment"> * specified, no log file will be used, and the spawn server</span>
440
+ <a name="l00425"></a>00425 <span class="comment"> * will use the same standard output/error channels as the</span>
441
+ <a name="l00426"></a>00426 <span class="comment"> * current process.</span>
442
+ <a name="l00427"></a>00427 <span class="comment"> * @param environment The RAILS_ENV environment that all RoR applications</span>
443
+ <a name="l00428"></a>00428 <span class="comment"> * should use. If an empty string is specified, the current value</span>
444
+ <a name="l00429"></a>00429 <span class="comment"> * of the RAILS_ENV environment variable will be used.</span>
445
+ <a name="l00430"></a>00430 <span class="comment"> * @param rubyCommand The Ruby interpreter's command.</span>
446
+ <a name="l00431"></a>00431 <span class="comment"> * @param user The user that the spawn manager should run as. This</span>
447
+ <a name="l00432"></a>00432 <span class="comment"> * parameter only has effect if the current process is</span>
448
+ <a name="l00433"></a>00433 <span class="comment"> * running as root. If the empty string is given, or if</span>
449
+ <a name="l00434"></a>00434 <span class="comment"> * the &lt;tt&gt;user&lt;/tt&gt; is not a valid username, then</span>
450
+ <a name="l00435"></a>00435 <span class="comment"> * the spawn manager will be run as the current user.</span>
451
+ <a name="l00436"></a>00436 <span class="comment"> * @throws SystemException An error occured while trying to setup the spawn server</span>
452
+ <a name="l00437"></a>00437 <span class="comment"> * or the server socket.</span>
453
+ <a name="l00438"></a>00438 <span class="comment"> * @throws IOException The specified log file could not be opened.</span>
454
+ <a name="l00439"></a>00439 <span class="comment"> */</span>
455
+ <a name="l00440"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html#3b63e995b09857659935132b6a4b97cc">00440</a> <a class="code" href="classPassenger_1_1ApplicationPoolServer.html#3b63e995b09857659935132b6a4b97cc" title="Create a new ApplicationPoolServer object.">ApplicationPoolServer</a>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;serverExecutable,
456
+ <a name="l00441"></a>00441 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;spawnServerCommand,
457
+ <a name="l00442"></a>00442 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;logFile = <span class="stringliteral">""</span>,
458
+ <a name="l00443"></a>00443 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;environment = <span class="stringliteral">"production"</span>,
459
+ <a name="l00444"></a>00444 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;rubyCommand = <span class="stringliteral">"ruby"</span>,
460
+ <a name="l00445"></a>00445 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;user = <span class="stringliteral">""</span>)
461
+ <a name="l00446"></a>00446 : m_serverExecutable(serverExecutable),
462
+ <a name="l00447"></a>00447 m_spawnServerCommand(spawnServerCommand),
463
+ <a name="l00448"></a>00448 m_logFile(logFile),
464
+ <a name="l00449"></a>00449 m_environment(environment),
465
+ <a name="l00450"></a>00450 m_rubyCommand(rubyCommand),
466
+ <a name="l00451"></a>00451 m_user(user) {
467
+ <a name="l00452"></a>00452 serverSocket = -1;
468
+ <a name="l00453"></a>00453 serverPid = 0;
469
+ <a name="l00454"></a>00454 restartServer();
470
+ <a name="l00455"></a>00455 }
471
+ <a name="l00456"></a>00456
472
+ <a name="l00457"></a>00457 ~<a class="code" href="classPassenger_1_1ApplicationPoolServer.html" title="Multi-process usage support for ApplicationPool.">ApplicationPoolServer</a>() {
473
+ <a name="l00458"></a>00458 <span class="keywordflow">if</span> (serverSocket != -1) {
474
+ <a name="l00459"></a>00459 shutdownServer();
475
+ <a name="l00460"></a>00460 }
476
+ <a name="l00461"></a>00461 }
477
+ <a name="l00462"></a>00462 <span class="comment"></span>
478
+ <a name="l00463"></a>00463 <span class="comment"> /**</span>
479
+ <a name="l00464"></a>00464 <span class="comment"> * Connects to the server and returns a usable ApplicationPool object.</span>
480
+ <a name="l00465"></a>00465 <span class="comment"> * All cache/pool data of this ApplicationPool is actually stored on</span>
481
+ <a name="l00466"></a>00466 <span class="comment"> * the server and shared with other clients, but that is totally</span>
482
+ <a name="l00467"></a>00467 <span class="comment"> * transparent to the user of the ApplicationPool object.</span>
483
+ <a name="l00468"></a>00468 <span class="comment"> *</span>
484
+ <a name="l00469"></a>00469 <span class="comment"> * @warning</span>
485
+ <a name="l00470"></a>00470 <span class="comment"> * One may only use the returned ApplicationPool object for handling</span>
486
+ <a name="l00471"></a>00471 <span class="comment"> * one session at a time. For example, don't do stuff like this:</span>
487
+ <a name="l00472"></a>00472 <span class="comment"> * @code</span>
488
+ <a name="l00473"></a>00473 <span class="comment"> * ApplicationPoolPtr pool = server.connect();</span>
489
+ <a name="l00474"></a>00474 <span class="comment"> * Application::SessionPtr session1 = pool-&gt;get(...);</span>
490
+ <a name="l00475"></a>00475 <span class="comment"> * Application::SessionPtr session2 = pool-&gt;get(...);</span>
491
+ <a name="l00476"></a>00476 <span class="comment"> * @endcode</span>
492
+ <a name="l00477"></a>00477 <span class="comment"> * Otherwise, a deadlock can occur under certain circumstances.</span>
493
+ <a name="l00478"></a>00478 <span class="comment"> * @warning</span>
494
+ <a name="l00479"></a>00479 <span class="comment"> * Instead, one should call connect() multiple times:</span>
495
+ <a name="l00480"></a>00480 <span class="comment"> * @code</span>
496
+ <a name="l00481"></a>00481 <span class="comment"> * ApplicationPoolPtr pool1 = server.connect();</span>
497
+ <a name="l00482"></a>00482 <span class="comment"> * Application::SessionPtr session1 = pool1-&gt;get(...);</span>
498
+ <a name="l00483"></a>00483 <span class="comment"> * </span>
499
+ <a name="l00484"></a>00484 <span class="comment"> * ApplicationPoolPtr pool2 = server.connect();</span>
500
+ <a name="l00485"></a>00485 <span class="comment"> * Application::SessionPtr session2 = pool2-&gt;get(...);</span>
501
+ <a name="l00486"></a>00486 <span class="comment"> * @endcode</span>
502
+ <a name="l00487"></a>00487 <span class="comment"> *</span>
503
+ <a name="l00488"></a>00488 <span class="comment"> * @throws SystemException Something went wrong.</span>
504
+ <a name="l00489"></a>00489 <span class="comment"> * @throws IOException Something went wrong.</span>
505
+ <a name="l00490"></a>00490 <span class="comment"> */</span>
506
+ <a name="l00491"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html#18f77057cc28e7924a8f4d1397aa0468">00491</a> ApplicationPoolPtr <a class="code" href="classPassenger_1_1ApplicationPoolServer.html#18f77057cc28e7924a8f4d1397aa0468" title="Connects to the server and returns a usable ApplicationPool object.">connect</a>() {
507
+ <a name="l00492"></a>00492 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a> channel(serverSocket);
508
+ <a name="l00493"></a>00493 <span class="keywordtype">int</span> clientConnection;
509
+ <a name="l00494"></a>00494
510
+ <a name="l00495"></a>00495 <span class="comment">// Write some random data to wake up the server.</span>
511
+ <a name="l00496"></a>00496 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);
512
+ <a name="l00497"></a>00497
513
+ <a name="l00498"></a>00498 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>();
514
+ <a name="l00499"></a>00499 <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));
515
+ <a name="l00500"></a>00500 }
516
+ <a name="l00501"></a>00501 <span class="comment"></span>
517
+ <a name="l00502"></a>00502 <span class="comment"> /**</span>
518
+ <a name="l00503"></a>00503 <span class="comment"> * Detach the server, thereby telling it that we don't want to connect</span>
519
+ <a name="l00504"></a>00504 <span class="comment"> * to it anymore. This frees up some resources in the current process,</span>
520
+ <a name="l00505"></a>00505 <span class="comment"> * such as file descriptors.</span>
521
+ <a name="l00506"></a>00506 <span class="comment"> *</span>
522
+ <a name="l00507"></a>00507 <span class="comment"> * This method is particularily useful to Apache worker processes that</span>
523
+ <a name="l00508"></a>00508 <span class="comment"> * have just established a connection with the ApplicationPool server.</span>
524
+ <a name="l00509"></a>00509 <span class="comment"> * Any sessions that are opened prior to calling detach(), will keep</span>
525
+ <a name="l00510"></a>00510 <span class="comment"> * working even after a detach().</span>
526
+ <a name="l00511"></a>00511 <span class="comment"> *</span>
527
+ <a name="l00512"></a>00512 <span class="comment"> * This method may only be called once. The ApplicationPoolServer object</span>
528
+ <a name="l00513"></a>00513 <span class="comment"> * will become unusable once detach() has been called, so call connect()</span>
529
+ <a name="l00514"></a>00514 <span class="comment"> * before calling detach().</span>
530
+ <a name="l00515"></a>00515 <span class="comment"> */</span>
531
+ <a name="l00516"></a><a class="code" href="classPassenger_1_1ApplicationPoolServer.html#b13957e32ae8ca36ba85f2e6ffefd5ce">00516</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1ApplicationPoolServer.html#b13957e32ae8ca36ba85f2e6ffefd5ce" title="Detach the server, thereby telling it that we don&amp;#39;t want to connect to it anymore...">detach</a>() {
532
+ <a name="l00517"></a>00517 close(serverSocket);
533
+ <a name="l00518"></a>00518 serverSocket = -1;
534
+ <a name="l00519"></a>00519 }
535
+ <a name="l00520"></a>00520 };
536
+ <a name="l00521"></a>00521
537
+ <a name="l00522"></a>00522 <span class="keyword">typedef</span> shared_ptr&lt;ApplicationPoolServer&gt; ApplicationPoolServerPtr;
538
+ <a name="l00523"></a>00523
539
+ <a name="l00524"></a>00524 } <span class="comment">// namespace Passenger</span>
540
+ <a name="l00525"></a>00525
541
+ <a name="l00526"></a>00526 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_APPLICATION_POOL_SERVER_H_ */</span>
542
+ </pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Wed May 7 13:56:13 2008 for Passenger by&nbsp;
542
543
  <a href="http://www.doxygen.org/index.html">
543
544
  <img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
544
545
  </body>