passenger 2.2.2 → 2.2.3

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 (254) hide show
  1. data/DEVELOPERS.TXT +13 -3
  2. data/Rakefile +42 -33
  3. data/bin/passenger-install-apache2-module +1 -2
  4. data/bin/passenger-install-nginx-module +7 -19
  5. data/bin/passenger-status +64 -15
  6. data/bin/passenger-stress-test +2 -2
  7. data/doc/ApplicationPool algorithm.txt +26 -22
  8. data/doc/Users guide Apache.html +374 -149
  9. data/doc/Users guide Apache.txt +318 -51
  10. data/doc/Users guide Nginx.html +13 -13
  11. data/doc/Users guide Nginx.txt +7 -2
  12. data/doc/cxxapi/Bucket_8h-source.html +62 -25
  13. data/doc/cxxapi/Configuration_8h-source.html +343 -326
  14. data/doc/cxxapi/DirectoryMapper_8h-source.html +12 -12
  15. data/doc/cxxapi/Hooks_8h-source.html +1 -1
  16. data/doc/cxxapi/annotated.html +1 -1
  17. data/doc/cxxapi/classHooks-members.html +1 -1
  18. data/doc/cxxapi/classHooks.html +1 -1
  19. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +2 -2
  20. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +9 -9
  21. data/doc/cxxapi/classes.html +1 -1
  22. data/doc/cxxapi/definitions_8h-source.html +1 -1
  23. data/doc/cxxapi/files.html +1 -1
  24. data/doc/cxxapi/functions.html +2 -2
  25. data/doc/cxxapi/functions_func.html +2 -2
  26. data/doc/cxxapi/graph_legend.html +1 -1
  27. data/doc/cxxapi/group__Configuration.html +1 -1
  28. data/doc/cxxapi/group__Core.html +1 -1
  29. data/doc/cxxapi/group__Hooks.html +1 -1
  30. data/doc/cxxapi/group__Support.html +1 -1
  31. data/doc/cxxapi/main.html +1 -1
  32. data/doc/cxxapi/modules.html +1 -1
  33. data/doc/rdoc/classes/ConditionVariable.html +194 -0
  34. data/doc/rdoc/classes/Exception.html +120 -0
  35. data/doc/rdoc/classes/GC.html +113 -0
  36. data/doc/rdoc/classes/IO.html +169 -0
  37. data/doc/rdoc/classes/PhusionPassenger.html +238 -0
  38. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +153 -0
  39. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +517 -0
  40. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +719 -0
  41. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +97 -0
  42. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +96 -0
  43. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +97 -0
  44. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +96 -0
  45. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +598 -0
  46. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +140 -0
  47. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +317 -0
  48. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +138 -0
  49. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +154 -0
  50. data/doc/rdoc/classes/PhusionPassenger/Application.html +283 -0
  51. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +172 -0
  52. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +145 -0
  53. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +175 -0
  54. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +141 -0
  55. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +92 -0
  56. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +489 -0
  57. data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +350 -0
  58. data/doc/rdoc/classes/PhusionPassenger/Rack.html +91 -0
  59. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +188 -0
  60. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +194 -0
  61. data/doc/rdoc/classes/PhusionPassenger/Railz.html +95 -0
  62. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +442 -0
  63. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +98 -0
  64. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +200 -0
  65. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +436 -0
  66. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +98 -0
  67. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +155 -0
  68. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +402 -0
  69. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +125 -0
  70. data/doc/rdoc/classes/PhusionPassenger/Utils.html +805 -0
  71. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +140 -0
  72. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +89 -0
  73. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +188 -0
  74. data/doc/rdoc/classes/PlatformInfo.html +831 -0
  75. data/doc/rdoc/classes/RakeExtensions.html +197 -0
  76. data/doc/rdoc/classes/Signal.html +131 -0
  77. data/doc/rdoc/created.rid +1 -0
  78. data/doc/rdoc/files/DEVELOPERS_TXT.html +255 -0
  79. data/doc/rdoc/files/README.html +157 -0
  80. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +92 -0
  81. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +129 -0
  82. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +131 -0
  83. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +126 -0
  84. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +130 -0
  85. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +130 -0
  86. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +122 -0
  87. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +127 -0
  88. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +126 -0
  89. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +122 -0
  90. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +134 -0
  91. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +122 -0
  92. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +122 -0
  93. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +126 -0
  94. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +122 -0
  95. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +122 -0
  96. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +127 -0
  97. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +133 -0
  98. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +127 -0
  99. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +143 -0
  100. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +126 -0
  101. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +145 -0
  102. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +127 -0
  103. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +122 -0
  104. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +161 -0
  105. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +175 -0
  106. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +129 -0
  107. data/doc/rdoc/files/misc/rake/extensions_rb.html +130 -0
  108. data/doc/rdoc/fr_class_index.html +90 -0
  109. data/doc/rdoc/fr_file_index.html +76 -0
  110. data/doc/rdoc/fr_method_index.html +200 -0
  111. data/doc/rdoc/index.html +26 -0
  112. data/doc/rdoc/rdoc-style.css +187 -0
  113. data/doc/users_guide_snippets/rackup_specifications.txt +2 -8
  114. data/ext/apache2/Bucket.cpp +71 -38
  115. data/ext/apache2/Bucket.h +53 -16
  116. data/ext/apache2/Configuration.cpp +15 -0
  117. data/ext/apache2/Configuration.h +19 -2
  118. data/ext/apache2/DirectoryMapper.h +10 -10
  119. data/ext/apache2/Hooks.cpp +334 -74
  120. data/ext/boost/mpl/apply.hpp +5 -1
  121. data/ext/boost/mpl/apply_wrap.hpp +5 -2
  122. data/ext/boost/mpl/aux_/full_lambda.hpp +5 -1
  123. data/ext/boost/mpl/bind.hpp +5 -1
  124. data/ext/common/Application.h +11 -31
  125. data/ext/common/ApplicationPool.h +2 -1
  126. data/ext/common/ApplicationPoolServer.h +61 -20
  127. data/ext/common/ApplicationPoolServerExecutable.cpp +132 -4
  128. data/ext/common/ApplicationPoolStatusReporter.h +189 -65
  129. data/ext/common/Base64.cpp +143 -0
  130. data/ext/common/Base64.h +57 -0
  131. data/ext/common/CachedFileStat.cpp +25 -82
  132. data/ext/common/CachedFileStat.h +11 -125
  133. data/ext/common/CachedFileStat.hpp +243 -0
  134. data/ext/common/Exceptions.h +13 -0
  135. data/ext/common/FileChangeChecker.h +209 -0
  136. data/ext/common/Logging.h +3 -2
  137. data/ext/common/MessageChannel.h +10 -10
  138. data/ext/common/PoolOptions.h +72 -5
  139. data/ext/common/SpawnManager.h +11 -8
  140. data/ext/common/StandardApplicationPool.h +38 -39
  141. data/ext/common/StaticString.h +1 -0
  142. data/ext/common/StringListCreator.h +83 -0
  143. data/ext/common/SystemTime.h +3 -2
  144. data/ext/common/Timer.h +88 -0
  145. data/ext/common/Utils.cpp +161 -42
  146. data/ext/common/Utils.h +62 -31
  147. data/ext/common/Version.h +1 -1
  148. data/ext/nginx/Configuration.c +0 -4
  149. data/ext/nginx/ContentHandler.c +8 -6
  150. data/ext/nginx/HelperServer.cpp +45 -55
  151. data/ext/nginx/HttpStatusExtractor.h +4 -0
  152. data/ext/nginx/StaticContentHandler.c +25 -5
  153. data/ext/nginx/config +3 -0
  154. data/ext/nginx/ngx_http_passenger_module.c +72 -17
  155. data/ext/nginx/ngx_http_passenger_module.h +2 -2
  156. data/lib/phusion_passenger/abstract_request_handler.rb +15 -7
  157. data/lib/phusion_passenger/abstract_server.rb +16 -2
  158. data/lib/phusion_passenger/admin_tools/control_process.rb +36 -25
  159. data/lib/phusion_passenger/constants.rb +1 -1
  160. data/lib/phusion_passenger/dependencies.rb +10 -0
  161. data/lib/phusion_passenger/platform_info.rb +1 -1
  162. data/lib/phusion_passenger/rack/application_spawner.rb +21 -2
  163. data/lib/phusion_passenger/rack/request_handler.rb +10 -0
  164. data/lib/phusion_passenger/railz/application_spawner.rb +38 -2
  165. data/lib/phusion_passenger/railz/framework_spawner.rb +26 -28
  166. data/lib/phusion_passenger/railz/request_handler.rb +5 -1
  167. data/lib/phusion_passenger/spawn_manager.rb +6 -2
  168. data/lib/phusion_passenger/utils.rb +79 -27
  169. data/misc/rake/cplusplus.rb +5 -5
  170. data/test/ApplicationPoolServerTest.cpp +42 -0
  171. data/test/ApplicationPoolTest.cpp +255 -267
  172. data/test/Base64Test.cpp +48 -0
  173. data/test/CachedFileStatTest.cpp +243 -103
  174. data/test/FileChangeCheckerTest.cpp +331 -0
  175. data/test/PoolOptionsTest.cpp +80 -0
  176. data/test/UtilsTest.cpp +5 -17
  177. data/test/integration_tests/apache2_tests.rb +15 -4
  178. data/test/integration_tests/mycook_spec.rb +3 -4
  179. data/test/oxt/syscall_interruption_test.cpp +2 -14
  180. data/test/ruby/abstract_server_collection_spec.rb +1 -1
  181. data/test/ruby/abstract_server_spec.rb +35 -1
  182. data/test/ruby/rack/application_spawner_spec.rb +23 -6
  183. data/test/ruby/rails/application_spawner_spec.rb +6 -6
  184. data/test/ruby/rails/framework_spawner_spec.rb +6 -5
  185. data/test/ruby/rails/minimal_spawner_spec.rb +19 -0
  186. data/test/ruby/rails/spawner_error_handling_spec.rb +62 -7
  187. data/test/ruby/spawn_manager_spec.rb +10 -7
  188. data/test/ruby/spawn_server_spec.rb +1 -1
  189. data/test/ruby/utils_spec.rb +193 -20
  190. data/test/ruby/wsgi/application_spawner_spec.rb +3 -1
  191. data/test/stub/apache2/httpd.conf.erb +3 -0
  192. data/test/stub/rack/config.ru +1 -1
  193. data/test/stub/rails_apps/mycook/app/controllers/welcome_controller.rb +8 -0
  194. data/test/support/Support.cpp +84 -0
  195. data/test/support/Support.h +66 -8
  196. data/test/support/config.rb +14 -2
  197. data/test/support/test_helper.rb +5 -0
  198. data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +123 -116
  199. data/vendor/rack-1.0.0-git/lib/rack/cascade.rb +17 -12
  200. data/vendor/rack-1.0.0-git/lib/rack/commonlogger.rb +34 -43
  201. data/vendor/rack-1.0.0-git/lib/rack/handler/cgi.rb +1 -1
  202. data/vendor/rack-1.0.0-git/lib/rack/handler/fastcgi.rb +1 -1
  203. data/vendor/rack-1.0.0-git/lib/rack/handler/lsws.rb +1 -1
  204. data/vendor/rack-1.0.0-git/lib/rack/handler/mongrel.rb +1 -1
  205. data/vendor/rack-1.0.0-git/lib/rack/handler/scgi.rb +1 -1
  206. data/vendor/rack-1.0.0-git/lib/rack/handler/webrick.rb +1 -1
  207. data/vendor/rack-1.0.0-git/lib/rack/mock.rb +4 -17
  208. data/vendor/rack-1.0.0-git/lib/rack/request.rb +3 -9
  209. data/vendor/rack-1.0.0-git/lib/rack/rewindable_input.rb +2 -0
  210. data/vendor/rack-1.0.0-git/lib/rack/utils.rb +38 -12
  211. metadata +231 -186
  212. data/ext/common/FileChecker.h +0 -112
  213. data/test/FileCheckerTest.cpp +0 -79
  214. data/test/stub/minimal-railsapp/README +0 -3
  215. data/test/stub/minimal-railsapp/config/application.rb +0 -0
  216. data/test/stub/minimal-railsapp/config/environment.rb +0 -3
  217. data/test/stub/minimal-railsapp/vendor/rails/actionmailer/lib/action_mailer.rb +0 -0
  218. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_controller.rb +0 -10
  219. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_pack.rb +0 -0
  220. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_view.rb +0 -0
  221. data/test/stub/minimal-railsapp/vendor/rails/activerecord/lib/active_record.rb +0 -7
  222. data/test/stub/minimal-railsapp/vendor/rails/activeresource/lib/active_resource.rb +0 -0
  223. data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support.rb +0 -17
  224. data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support/whiny_nil.rb +0 -0
  225. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/dispatcher.rb +0 -0
  226. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/initializer.rb +0 -8
  227. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/ruby_version_check.rb +0 -1
  228. data/test/stub/railsapp/app/controllers/application.rb +0 -12
  229. data/test/stub/railsapp/app/controllers/bar_controller.rb +0 -5
  230. data/test/stub/railsapp/app/controllers/bar_controller_1.txt +0 -5
  231. data/test/stub/railsapp/app/controllers/bar_controller_2.txt +0 -5
  232. data/test/stub/railsapp/app/controllers/foo_controller.rb +0 -9
  233. data/test/stub/railsapp/app/helpers/application_helper.rb +0 -3
  234. data/test/stub/railsapp/config/boot.rb +0 -108
  235. data/test/stub/railsapp/config/database.yml +0 -19
  236. data/test/stub/railsapp/config/environment.rb +0 -59
  237. data/test/stub/railsapp/config/environments/development.rb +0 -18
  238. data/test/stub/railsapp/config/environments/production.rb +0 -19
  239. data/test/stub/railsapp/config/initializers/inflections.rb +0 -10
  240. data/test/stub/railsapp/config/initializers/mime_types.rb +0 -5
  241. data/test/stub/railsapp/config/routes.rb +0 -35
  242. data/test/stub/railsapp/public/useless.txt +0 -1
  243. data/test/stub/railsapp2/app/controllers/application.rb +0 -12
  244. data/test/stub/railsapp2/app/controllers/foo_controller.rb +0 -5
  245. data/test/stub/railsapp2/app/helpers/application_helper.rb +0 -3
  246. data/test/stub/railsapp2/config/boot.rb +0 -108
  247. data/test/stub/railsapp2/config/database.yml +0 -19
  248. data/test/stub/railsapp2/config/environment.rb +0 -59
  249. data/test/stub/railsapp2/config/environments/development.rb +0 -18
  250. data/test/stub/railsapp2/config/environments/production.rb +0 -19
  251. data/test/stub/railsapp2/config/initializers/inflections.rb +0 -10
  252. data/test/stub/railsapp2/config/initializers/mime_types.rb +0 -5
  253. data/test/stub/railsapp2/config/routes.rb +0 -35
  254. data/test/stub/railsapp2/public/useless.txt +0 -1
data/ext/common/Logging.h CHANGED
@@ -64,8 +64,9 @@ void setDebugFile(const char *logFile = NULL);
64
64
  strftime(datetime_buf, sizeof(datetime_buf), "%F %H:%M:%S", the_tm); \
65
65
  gettimeofday(&tv, NULL); \
66
66
  sstream << \
67
- "[ pid=" << getpid() << " file=" << __FILE__ << ":" << __LINE__ << \
68
- " time=" << datetime_buf << "." << (tv.tv_usec / 1000) << " ]:" << \
67
+ "[ pid=" << ((unsigned long) getpid()) << \
68
+ " file=" << __FILE__ << ":" << (unsigned long) __LINE__ << \
69
+ " time=" << datetime_buf << "." << (unsigned long) (tv.tv_usec / 1000) << " ]:" << \
69
70
  "\n " << expr << std::endl; \
70
71
  *stream << sstream.str(); \
71
72
  stream->flush(); \
@@ -570,11 +570,11 @@ public:
570
570
  ret = syscalls::setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
571
571
  &tv, sizeof(tv));
572
572
  #ifndef __SOLARIS__
573
- // SO_RCVTIMEO is unimplemented and retuns an error on Solaris
574
- // 9 and 10 SPARC. Seems to work okay without it.
575
- if (ret == -1) {
576
- throw SystemException("Cannot set read timeout for socket", errno);
577
- }
573
+ // SO_RCVTIMEO is unimplemented and returns an error on Solaris
574
+ // 9 and 10 SPARC. Seems to work okay without it.
575
+ if (ret == -1) {
576
+ throw SystemException("Cannot set read timeout for socket", errno);
577
+ }
578
578
  #endif
579
579
  }
580
580
 
@@ -601,11 +601,11 @@ public:
601
601
  ret = syscalls::setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
602
602
  &tv, sizeof(tv));
603
603
  #ifndef __SOLARIS__
604
- // SO_SNDTIMEO is unimplemented and returns an error on Solaris
605
- // 9 and 10 SPARC. Seems to work okay without it.
606
- if (ret == -1) {
607
- throw SystemException("Cannot set read timeout for socket", errno);
608
- }
604
+ // SO_SNDTIMEO is unimplemented and returns an error on Solaris
605
+ // 9 and 10 SPARC. Seems to work okay without it.
606
+ if (ret == -1) {
607
+ throw SystemException("Cannot set read timeout for socket", errno);
608
+ }
609
609
  #endif
610
610
  }
611
611
  };
@@ -26,7 +26,8 @@
26
26
  #define _PASSENGER_SPAWN_OPTIONS_H_
27
27
 
28
28
  #include <string>
29
- #include "Utils.h"
29
+ #include <vector>
30
+ #include "StringListCreator.h"
30
31
 
31
32
  namespace Passenger {
32
33
 
@@ -147,6 +148,29 @@ struct PoolOptions {
147
148
  */
148
149
  string restartDir;
149
150
 
151
+ /**
152
+ * If a new backend process is started, then the getItems() method
153
+ * on this object will be called, which is to return environment
154
+ * variables that should be passed to the newly spawned backend process.
155
+ * Odd indices in the resulting array contain keys, even indices contain
156
+ * the value for the key in the previous index.
157
+ *
158
+ * May be set to NULL.
159
+ *
160
+ * @invariant environmentVariables.size() is an even number.
161
+ */
162
+ StringListCreatorPtr environmentVariables;
163
+
164
+ /**
165
+ * The base URI on which the application runs. If the application is
166
+ * running on the root URI, then this value must be "/".
167
+ *
168
+ * @invariant baseURI != ""
169
+ */
170
+ string baseURI;
171
+
172
+ /*********************************/
173
+
150
174
  /**
151
175
  * Creates a new PoolOptions object with the default values filled in.
152
176
  * One must still set appRoot manually, after having used this constructor.
@@ -163,6 +187,7 @@ struct PoolOptions {
163
187
  memoryLimit = 0;
164
188
  useGlobalQueue = false;
165
189
  statThrottleRate = 0;
190
+ baseURI = "/";
166
191
  }
167
192
 
168
193
  /**
@@ -180,7 +205,8 @@ struct PoolOptions {
180
205
  unsigned long memoryLimit = 0,
181
206
  bool useGlobalQueue = false,
182
207
  unsigned long statThrottleRate = 0,
183
- const string &restartDir = ""
208
+ const string &restartDir = "",
209
+ const string &baseURI = "/"
184
210
  ) {
185
211
  this->appRoot = appRoot;
186
212
  this->lowerPrivilege = lowerPrivilege;
@@ -195,6 +221,7 @@ struct PoolOptions {
195
221
  this->useGlobalQueue = useGlobalQueue;
196
222
  this->statThrottleRate = statThrottleRate;
197
223
  this->restartDir = restartDir;
224
+ this->baseURI = baseURI;
198
225
  }
199
226
 
200
227
  /**
@@ -230,16 +257,24 @@ struct PoolOptions {
230
257
  useGlobalQueue = vec[startIndex + 21] == "true";
231
258
  statThrottleRate = atol(vec[startIndex + 23]);
232
259
  restartDir = vec[startIndex + 25];
260
+ baseURI = vec[startIndex + 27];
261
+ if (vec.size() > startIndex + 29) {
262
+ environmentVariables = ptr(new SimpleStringListCreator(vec[startIndex + 29]));
263
+ }
233
264
  }
234
265
 
235
266
  /**
236
267
  * Append the information in this PoolOptions object to the given
237
268
  * string vector. The resulting array could, for example, be used
238
269
  * as a message to be sent to the spawn server.
270
+ *
271
+ * @param vec The vector to store the information in.
272
+ * @param storeEnvVars Whether to store environment variable information into vec as well.
273
+ * @throws Anything thrown by environmentVariables->getItems().
239
274
  */
240
- void toVector(vector<string> &vec) const {
241
- if (vec.capacity() < vec.size() + 10) {
242
- vec.reserve(vec.size() + 10);
275
+ void toVector(vector<string> &vec, bool storeEnvVars = true) const {
276
+ if (vec.capacity() < vec.size() + 30) {
277
+ vec.reserve(vec.size() + 30);
243
278
  }
244
279
  appendKeyValue (vec, "app_root", appRoot);
245
280
  appendKeyValue (vec, "lower_privilege", lowerPrivilege ? "true" : "false");
@@ -254,6 +289,38 @@ struct PoolOptions {
254
289
  appendKeyValue (vec, "use_global_queue", useGlobalQueue ? "true" : "false");
255
290
  appendKeyValue3(vec, "stat_throttle_rate", statThrottleRate);
256
291
  appendKeyValue (vec, "restart_dir", restartDir);
292
+ appendKeyValue (vec, "base_uri", baseURI);
293
+ if (storeEnvVars) {
294
+ vec.push_back("environment_variables");
295
+ vec.push_back(serializeEnvironmentVariables());
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Serializes the items in environmentVariables into a string, which
301
+ * can be used to create a SimpleStringListCreator object.
302
+ *
303
+ * @throws Anything thrown by environmentVariables->getItems().
304
+ */
305
+ string serializeEnvironmentVariables() const {
306
+ vector<string>::const_iterator it, end;
307
+ string result;
308
+
309
+ if (environmentVariables) {
310
+ result.reserve(1024);
311
+
312
+ StringListPtr items = environmentVariables->getItems();
313
+ end = items->end();
314
+
315
+ for (it = items->begin(); it != end; it++) {
316
+ result.append(*it);
317
+ result.append(1, '\0');
318
+ it++;
319
+ result.append(*it);
320
+ result.append(1, '\0');
321
+ }
322
+ }
323
+ return Base64::encode(result);
257
324
  }
258
325
 
259
326
  private:
@@ -265,15 +265,16 @@ private:
265
265
  * @param PoolOptions The spawn options to use.
266
266
  * @return An Application smart pointer, representing the spawned application.
267
267
  * @throws SpawnException Something went wrong.
268
+ * @throws Anything thrown by options.environmentVariables->getItems().
268
269
  */
269
- ApplicationPtr sendSpawnCommand(const PoolOptions &PoolOptions) {
270
+ ApplicationPtr sendSpawnCommand(const PoolOptions &options) {
270
271
  TRACE_POINT();
271
272
  vector<string> args;
272
273
  int ownerPipe;
273
274
 
274
275
  try {
275
276
  args.push_back("spawn_application");
276
- PoolOptions.toVector(args);
277
+ options.toVector(args);
277
278
  channel.write(args);
278
279
  } catch (const SystemException &e) {
279
280
  throw SpawnException(string("Could not write 'spawn_application' "
@@ -346,15 +347,16 @@ private:
346
347
  ret = chown(args[1].c_str(), getuid(), getgid());
347
348
  } while (ret == -1 && errno == EINTR);
348
349
  }
349
- return ApplicationPtr(new Application(PoolOptions.appRoot,
350
+ return ApplicationPtr(new Application(options.appRoot,
350
351
  pid, args[1], args[2], ownerPipe));
351
352
  }
352
353
 
353
354
  /**
354
355
  * @throws boost::thread_interrupted
356
+ * @throws Anything thrown by options.environmentVariables->getItems().
355
357
  */
356
358
  ApplicationPtr
357
- handleSpawnException(const SpawnException &e, const PoolOptions &PoolOptions) {
359
+ handleSpawnException(const SpawnException &e, const PoolOptions &options) {
358
360
  TRACE_POINT();
359
361
  bool restarted;
360
362
  try {
@@ -371,7 +373,7 @@ private:
371
373
  restarted = false;
372
374
  }
373
375
  if (restarted) {
374
- return sendSpawnCommand(PoolOptions);
376
+ return sendSpawnCommand(options);
375
377
  } else {
376
378
  throw SpawnException("The spawn server died unexpectedly, and restarting it failed.");
377
379
  }
@@ -500,17 +502,18 @@ public:
500
502
  * spawned application.
501
503
  * @throws SpawnException Something went wrong.
502
504
  * @throws boost::thread_interrupted
505
+ * @throws Anything thrown by options.environmentVariables->getItems().
503
506
  */
504
- ApplicationPtr spawn(const PoolOptions &PoolOptions) {
507
+ ApplicationPtr spawn(const PoolOptions &options) {
505
508
  TRACE_POINT();
506
509
  boost::mutex::scoped_lock l(lock);
507
510
  try {
508
- return sendSpawnCommand(PoolOptions);
511
+ return sendSpawnCommand(options);
509
512
  } catch (const SpawnException &e) {
510
513
  if (e.hasErrorPage()) {
511
514
  throw;
512
515
  } else {
513
- return handleSpawnException(e, PoolOptions);
516
+ return handleSpawnException(e, options);
514
517
  }
515
518
  }
516
519
  }
@@ -52,8 +52,8 @@
52
52
 
53
53
  #include "ApplicationPool.h"
54
54
  #include "Logging.h"
55
- #include "FileChecker.h"
56
- #include "CachedFileStat.h"
55
+ #include "FileChangeChecker.h"
56
+ #include "CachedFileStat.hpp"
57
57
  #ifdef PASSENGER_USE_DUMMY_SPAWN_MANAGER
58
58
  #include "DummySpawnManager.h"
59
59
  #else
@@ -121,25 +121,6 @@ private:
121
121
  AppContainerList instances;
122
122
  unsigned int size;
123
123
  unsigned long maxRequests;
124
- FileChecker restartFileChecker;
125
- CachedFileStat alwaysRestartFileStatter;
126
-
127
- Domain(const PoolOptions &options)
128
- : restartFileChecker(determineRestartDir(options) + "/restart.txt"),
129
- alwaysRestartFileStatter(determineRestartDir(options) + "/always_restart.txt")
130
- {
131
- }
132
-
133
- private:
134
- static string determineRestartDir(const PoolOptions &options) {
135
- if (options.restartDir.empty()) {
136
- return options.appRoot + "/tmp";
137
- } else if (options.restartDir[0] == '/') {
138
- return options.restartDir;
139
- } else {
140
- return options.appRoot + "/" + options.restartDir;
141
- }
142
- }
143
124
  };
144
125
 
145
126
  struct AppContainer {
@@ -267,6 +248,8 @@ private:
267
248
  unsigned int maxIdleTime;
268
249
  unsigned int waitingOnGlobalQueue;
269
250
  condition cleanerThreadSleeper;
251
+ CachedFileStat cstat;
252
+ FileChangeChecker fileChangeChecker;
270
253
 
271
254
  // Shortcuts for instance variables in SharedData. Saves typing in get().
272
255
  boost::mutex &lock;
@@ -364,12 +347,24 @@ private:
364
347
  /**
365
348
  * Checks whether the given application domain needs to be restarted.
366
349
  *
367
- * @throws SystemException Something went wrong while retrieving the system time.
350
+ * @throws TimeRetrievalException Something went wrong while retrieving the system time.
368
351
  * @throws boost::thread_interrupted
369
352
  */
370
- bool needsRestart(const string &appRoot, Domain *domain, const PoolOptions &options) {
371
- return domain->alwaysRestartFileStatter.refresh(options.statThrottleRate) == 0
372
- || domain->restartFileChecker.changed(options.statThrottleRate);
353
+ bool needsRestart(const string &appRoot, const PoolOptions &options) {
354
+ string restartDir;
355
+ if (options.restartDir.empty()) {
356
+ restartDir = appRoot + "/tmp";
357
+ } else if (options.restartDir[0] == '/') {
358
+ restartDir = options.restartDir;
359
+ } else {
360
+ restartDir = appRoot + "/" + options.restartDir;
361
+ }
362
+
363
+ string alwaysRestartFile = restartDir + "/always_restart.txt";
364
+ string restartFile = restartDir + "/restart.txt";
365
+ struct stat buf;
366
+ return cstat.stat(alwaysRestartFile, &buf, options.statThrottleRate) == 0 ||
367
+ fileChangeChecker.changed(restartFile, options.statThrottleRate);
373
368
  }
374
369
 
375
370
  void cleanerThreadMainLoop() {
@@ -430,6 +425,7 @@ private:
430
425
  * @throws boost::thread_interrupted
431
426
  * @throws SpawnException
432
427
  * @throws SystemException
428
+ * @throws TimeRetrievalException Something went wrong while retrieving the system time.
433
429
  */
434
430
  pair<AppContainerPtr, Domain *>
435
431
  spawnOrUseExisting(boost::mutex::scoped_lock &l, const PoolOptions &options) {
@@ -446,21 +442,24 @@ private:
446
442
  try {
447
443
  DomainMap::iterator it(domains.find(appRoot));
448
444
 
449
- if (it != domains.end() && needsRestart(appRoot, it->second.get(), options)) {
450
- AppContainerList::iterator it2;
451
- instances = &it->second->instances;
452
- for (it2 = instances->begin(); it2 != instances->end(); it2++) {
453
- container = *it2;
454
- if (container->sessions == 0) {
455
- inactiveApps.erase(container->ia_iterator);
456
- } else {
457
- active--;
445
+ if (needsRestart(appRoot, options)) {
446
+ if (it != domains.end()) {
447
+ AppContainerList::iterator it2;
448
+ instances = &it->second->instances;
449
+ for (it2 = instances->begin(); it2 != instances->end(); it2++) {
450
+ container = *it2;
451
+ if (container->sessions == 0) {
452
+ inactiveApps.erase(container->ia_iterator);
453
+ } else {
454
+ active--;
455
+ }
456
+ it2--;
457
+ instances->erase(container->iterator);
458
+ count--;
458
459
  }
459
- it2--;
460
- instances->erase(container->iterator);
461
- count--;
460
+ domains.erase(appRoot);
462
461
  }
463
- domains.erase(appRoot);
462
+ P_DEBUG("Restarting " << appRoot);
464
463
  spawnManager.reload(appRoot);
465
464
  it = domains.end();
466
465
  activeOrMaxChanged.notify_all();
@@ -548,7 +547,7 @@ private:
548
547
  container->sessions = 0;
549
548
  it = domains.find(appRoot);
550
549
  if (it == domains.end()) {
551
- domain = new Domain(options);
550
+ domain = new Domain();
552
551
  domain->size = 1;
553
552
  domain->maxRequests = options.maxRequests;
554
553
  domains[appRoot] = ptr(domain);
@@ -26,6 +26,7 @@
26
26
  #define _PASSENGER_STATIC_STRING_H_
27
27
 
28
28
  #include <string>
29
+ #include <cstring>
29
30
 
30
31
  namespace Passenger {
31
32
 
@@ -0,0 +1,83 @@
1
+ /*
2
+ * Phusion Passenger - http://www.modrails.com/
3
+ * Copyright (c) 2009 Phusion
4
+ *
5
+ * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ */
25
+ #ifndef _PASSENGER_STRING_LIST_CREATOR_H_
26
+ #define _PASSENGER_STRING_LIST_CREATOR_H_
27
+
28
+ #include <string>
29
+ #include <vector>
30
+ #include <boost/shared_ptr.hpp>
31
+ #include "Base64.h"
32
+ #include "Utils.h"
33
+
34
+ namespace Passenger {
35
+
36
+ using namespace std;
37
+ using namespace boost;
38
+
39
+ typedef vector<string> StringList;
40
+ typedef shared_ptr<StringList> StringListPtr;
41
+
42
+
43
+ class StringListCreator {
44
+ public:
45
+ virtual ~StringListCreator() {}
46
+
47
+ /** May throw arbitrary exceptions. */
48
+ virtual const StringListPtr getItems() const = 0;
49
+ };
50
+
51
+ typedef shared_ptr<StringListCreator> StringListCreatorPtr;
52
+
53
+ class SimpleStringListCreator: public StringListCreator {
54
+ public:
55
+ StringListPtr items;
56
+
57
+ SimpleStringListCreator() {
58
+ items = ptr(new StringList());
59
+ }
60
+
61
+ SimpleStringListCreator(const StaticString &data) {
62
+ items = ptr(new StringList());
63
+ string buffer = Base64::decode(data);
64
+ if (!buffer.empty()) {
65
+ string::size_type start = 0, pos;
66
+ const string &const_buffer(buffer);
67
+ while ((pos = const_buffer.find('\0', start)) != string::npos) {
68
+ items->push_back(const_buffer.substr(start, pos - start));
69
+ start = pos + 1;
70
+ }
71
+ }
72
+ }
73
+
74
+ virtual const StringListPtr getItems() const {
75
+ return items;
76
+ }
77
+ };
78
+
79
+ typedef shared_ptr<SimpleStringListCreator> SimpleStringListCreatorPtr;
80
+
81
+ } // namespace Passenger
82
+
83
+ #endif /* _PASSENGER_STRING_LIST_CREATOR_H_ */