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
@@ -87,6 +87,7 @@ passenger_config_create_dir(apr_pool_t *p, char *dirspec) {
87
87
  config->statThrottleRate = 0;
88
88
  config->statThrottleRateSpecified = false;
89
89
  config->restartDir = NULL;
90
+ config->uploadBufferDir = NULL;
90
91
  /*************************************/
91
92
  return config;
92
93
  }
@@ -127,6 +128,7 @@ passenger_config_merge_dir(apr_pool_t *p, void *basev, void *addv) {
127
128
  config->statThrottleRate = (add->statThrottleRateSpecified) ? add->statThrottleRate : base->statThrottleRate;
128
129
  config->statThrottleRateSpecified = base->statThrottleRateSpecified || add->statThrottleRateSpecified;
129
130
  config->restartDir = (add->restartDir == NULL) ? base->restartDir : add->restartDir;
131
+ config->uploadBufferDir = (add->uploadBufferDir == NULL) ? base->uploadBufferDir : add->uploadBufferDir;
130
132
  /*************************************/
131
133
  return config;
132
134
  }
@@ -401,6 +403,13 @@ cmd_passenger_app_root(cmd_parms *cmd, void *pcfg, const char *arg) {
401
403
  return NULL;
402
404
  }
403
405
 
406
+ static const char *
407
+ cmd_passenger_upload_buffer_dir(cmd_parms *cmd, void *pcfg, const char *arg) {
408
+ DirConfig *config = (DirConfig *) pcfg;
409
+ config->uploadBufferDir = arg;
410
+ return NULL;
411
+ }
412
+
404
413
 
405
414
  /*************************************************
406
415
  * Rails-specific settings
@@ -622,6 +631,12 @@ const command_rec passenger_commands[] = {
622
631
  NULL,
623
632
  OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
624
633
  "The application's root directory."),
634
+ AP_INIT_TAKE1("PassengerUploadBufferDir",
635
+ (Take1Func) cmd_passenger_upload_buffer_dir,
636
+ NULL,
637
+ OR_OPTIONS,
638
+ "The directory in which upload buffer files should be placed."),
639
+ /*****************************/
625
640
 
626
641
  // Rails-specific settings.
627
642
  AP_INIT_TAKE1("RailsBaseURI",
@@ -25,8 +25,10 @@
25
25
  #ifndef _PASSENGER_CONFIGURATION_H_
26
26
  #define _PASSENGER_CONFIGURATION_H_
27
27
 
28
- #include "Utils.h"
29
- #include "MessageChannel.h"
28
+ #ifdef __cplusplus
29
+ #include "Utils.h"
30
+ #include "MessageChannel.h"
31
+ #endif
30
32
 
31
33
  /* The APR headers must come after the Passenger headers. See Hooks.cpp
32
34
  * to learn why.
@@ -153,6 +155,13 @@
153
155
  */
154
156
  const char *restartDir;
155
157
 
158
+ /**
159
+ * The directory in which Passenger should place upload buffer
160
+ * files. NULL means that the default directory should be used.
161
+ */
162
+ const char *uploadBufferDir;
163
+
164
+ /*************************************/
156
165
  /*************************************/
157
166
 
158
167
  bool isEnabled() const {
@@ -244,6 +253,14 @@
244
253
  }
245
254
  }
246
255
 
256
+ string getUploadBufferDir() const {
257
+ if (uploadBufferDir != NULL) {
258
+ return uploadBufferDir;
259
+ } else {
260
+ return getPassengerTempDir() + "/webserver_private";
261
+ }
262
+ }
263
+
247
264
  /*************************************/
248
265
  };
249
266
 
@@ -31,7 +31,7 @@
31
31
 
32
32
  #include <oxt/backtrace.hpp>
33
33
 
34
- #include "CachedFileStat.h"
34
+ #include "CachedFileStat.hpp"
35
35
  #include "Configuration.h"
36
36
  #include "Utils.h"
37
37
 
@@ -66,7 +66,7 @@ public:
66
66
  private:
67
67
  DirConfig *config;
68
68
  request_rec *r;
69
- CachedMultiFileStat *mstat;
69
+ CachedFileStat *cstat;
70
70
  unsigned int throttleRate;
71
71
  bool baseURIKnown;
72
72
  const char *baseURI;
@@ -91,16 +91,16 @@ public:
91
91
  /**
92
92
  * Create a new DirectoryMapper object.
93
93
  *
94
- * @param mstat A CachedMultiFileStat object used for statting files.
95
- * @param throttleRate A throttling rate for mstat.
94
+ * @param cstat A CachedFileStat object used for statting files.
95
+ * @param throttleRate A throttling rate for cstat.
96
96
  * @warning Do not use this object after the destruction of <tt>r</tt>,
97
- * <tt>config</tt> or <tt>mstat</tt>.
97
+ * <tt>config</tt> or <tt>cstat</tt>.
98
98
  */
99
99
  DirectoryMapper(request_rec *r, DirConfig *config,
100
- CachedMultiFileStat *mstat, unsigned int throttleRate) {
100
+ CachedFileStat *cstat, unsigned int throttleRate) {
101
101
  this->r = r;
102
102
  this->config = config;
103
- this->mstat = mstat;
103
+ this->cstat = cstat;
104
104
  this->throttleRate = throttleRate;
105
105
  appType = NONE;
106
106
  baseURIKnown = false;
@@ -171,7 +171,7 @@ public:
171
171
 
172
172
  UPDATE_TRACE_POINT();
173
173
  if (shouldAutoDetectRails()
174
- && verifyRailsDir(config->getAppRoot(ap_document_root(r)), mstat, throttleRate)) {
174
+ && verifyRailsDir(config->getAppRoot(ap_document_root(r)), cstat, throttleRate)) {
175
175
  baseURIKnown = true;
176
176
  baseURI = "/";
177
177
  appType = RAILS;
@@ -180,7 +180,7 @@ public:
180
180
 
181
181
  UPDATE_TRACE_POINT();
182
182
  if (shouldAutoDetectRack()
183
- && verifyRackDir(config->getAppRoot(ap_document_root(r)), mstat, throttleRate)) {
183
+ && verifyRackDir(config->getAppRoot(ap_document_root(r)), cstat, throttleRate)) {
184
184
  baseURIKnown = true;
185
185
  baseURI = "/";
186
186
  appType = RACK;
@@ -189,7 +189,7 @@ public:
189
189
 
190
190
  UPDATE_TRACE_POINT();
191
191
  if (shouldAutoDetectWSGI()
192
- && verifyWSGIDir(config->getAppRoot(ap_document_root(r)), mstat, throttleRate)) {
192
+ && verifyWSGIDir(config->getAppRoot(ap_document_root(r)), cstat, throttleRate)) {
193
193
  baseURIKnown = true;
194
194
  baseURI = "/";
195
195
  appType = WSGI;
@@ -39,6 +39,7 @@
39
39
  #include "ApplicationPoolServer.h"
40
40
  #include "MessageChannel.h"
41
41
  #include "DirectoryMapper.h"
42
+ #include "Timer.h"
42
43
  #include "Version.h"
43
44
 
44
45
  /* The Apache/APR headers *must* come after the Boost headers, otherwise
@@ -138,12 +139,44 @@ private:
138
139
  }
139
140
  };
140
141
 
142
+ /**
143
+ * A StringListCreator which returns a list of environment variable
144
+ * names and values, as found in r->subprocess_env.
145
+ */
146
+ class EnvironmentVariablesStringListCreator: public StringListCreator {
147
+ private:
148
+ request_rec *r;
149
+ public:
150
+ EnvironmentVariablesStringListCreator(request_rec *r) {
151
+ this->r = r;
152
+ }
153
+
154
+ virtual const StringListPtr getItems() const {
155
+ const apr_array_header_t *env_arr;
156
+ apr_table_entry_t *env_entries;
157
+ StringListPtr result = ptr(new StringList());
158
+
159
+ // Some standard CGI headers.
160
+ result->push_back("SERVER_SOFTWARE");
161
+ result->push_back(ap_get_server_version());
162
+
163
+ // Subprocess environment variables.
164
+ env_arr = apr_table_elts(r->subprocess_env);
165
+ env_entries = (apr_table_entry_t *) env_arr->elts;
166
+ for (int i = 0; i < env_arr->nelts; ++i) {
167
+ result->push_back(env_entries[i].key);
168
+ result->push_back(env_entries[i].val);
169
+ }
170
+ return result;
171
+ }
172
+ };
173
+
141
174
  enum Threeway { YES, NO, UNKNOWN };
142
175
 
143
176
  ApplicationPoolServerPtr applicationPoolServer;
144
177
  thread_specific_ptr<ApplicationPoolPtr> threadSpecificApplicationPool;
145
178
  Threeway m_hasModRewrite, m_hasModDir, m_hasModAutoIndex;
146
- CachedMultiFileStat *mstat;
179
+ CachedFileStat cstat;
147
180
 
148
181
  inline DirConfig *getDirConfig(request_rec *r) {
149
182
  return (DirConfig *) ap_get_module_config(r->per_dir_config, &passenger_module);
@@ -249,7 +282,7 @@ private:
249
282
  * (C) r->filename already exists.
250
283
  * (D) There is a page cache file for the URI.
251
284
  *
252
- * - If A is not true, or if B is not true, or if C is true, then won't do anything.
285
+ * - If A is not true, or if B is not true, or if C is true, then don't do anything.
253
286
  * Passenger will be disabled during the rest of this request.
254
287
  * - If D is true, then we first transform r->filename to the page cache file's
255
288
  * filename, and then we let Apache serve it statically.
@@ -261,7 +294,7 @@ private:
261
294
  */
262
295
  bool prepareRequest(request_rec *r, DirConfig *config, const char *filename, bool coreModuleWillBeRun = false) {
263
296
  TRACE_POINT();
264
- DirectoryMapper mapper(r, config, mstat, config->getStatThrottleRate());
297
+ DirectoryMapper mapper(r, config, &cstat, config->getStatThrottleRate());
265
298
  try {
266
299
  if (mapper.getBaseURI() == NULL) {
267
300
  // (B) is not true.
@@ -378,6 +411,9 @@ private:
378
411
  void *pointer;
379
412
  } u;
380
413
 
414
+ /* Did an error occur in any of the previous hook methods during
415
+ * this request? If so, show the error and stop here.
416
+ */
381
417
  u.errorReport = 0;
382
418
  apr_pool_userdata_get(&u.pointer, "Phusion Passenger: error report", r->pool);
383
419
  if (u.errorReport != 0) {
@@ -411,8 +447,6 @@ private:
411
447
  try {
412
448
  this_thread::disable_interruption di;
413
449
  this_thread::disable_syscall_interruption dsi;
414
- apr_bucket_brigade *bb;
415
- apr_bucket *b;
416
450
  Application::SessionPtr session;
417
451
  bool expectingUploadData;
418
452
  shared_ptr<BufferedUpload> uploadData;
@@ -421,10 +455,11 @@ private:
421
455
  expectingUploadData = ap_should_client_block(r);
422
456
  contentLength = lookupHeader(r, "Content-Length");
423
457
 
424
- // If the HTTP upload data is larger than a threshold, or if the HTTP
425
- // client sent HTTP upload data using the "chunked" transfer encoding
426
- // (which implies Content-Length == NULL), then buffer the upload
427
- // data into a tempfile.
458
+ /* If the HTTP upload data is larger than a threshold, or if the HTTP
459
+ * client sent HTTP upload data using the "chunked" transfer encoding
460
+ * (which implies Content-Length == NULL), then buffer the upload
461
+ * data into a tempfile.
462
+ */
428
463
  if (expectingUploadData && (
429
464
  contentLength == NULL ||
430
465
  atol(contentLength) > UPLOAD_ACCELERATION_THRESHOLD
@@ -434,10 +469,11 @@ private:
434
469
  }
435
470
 
436
471
  if (expectingUploadData && contentLength == NULL) {
437
- // In case of "chunked" transfer encoding, we'll set the
438
- // Content-Length header to the length of the received upload
439
- // data. Rails requires this header for its HTTP upload data
440
- // multipart parsing process.
472
+ /* In case of "chunked" transfer encoding, we'll set the
473
+ * Content-Length header to the length of the received upload
474
+ * data. Rails requires this header for its HTTP upload data
475
+ * multipart parsing process.
476
+ */
441
477
  apr_table_set(r->headers_in, "Content-Length",
442
478
  toString(ftell(uploadData->handle)).c_str());
443
479
  }
@@ -450,10 +486,8 @@ private:
450
486
  try {
451
487
  ServerConfig *sconfig = getServerConfig(r->server);
452
488
  string publicDirectory(mapper.getPublicDirectory());
453
- string appRoot(config->getAppRoot(publicDirectory.c_str()));
454
-
455
- session = getApplicationPool()->get(PoolOptions(
456
- appRoot,
489
+ PoolOptions options(
490
+ config->getAppRoot(publicDirectory.c_str()),
457
491
  true,
458
492
  sconfig->getDefaultUser(),
459
493
  mapper.getEnvironment(),
@@ -465,8 +499,12 @@ private:
465
499
  config->getMemoryLimit(),
466
500
  config->usingGlobalQueue(),
467
501
  config->getStatThrottleRate(),
468
- config->getRestartDir()
469
- ));
502
+ config->getRestartDir(),
503
+ mapper.getBaseURI()
504
+ );
505
+ options.environmentVariables = ptr(new EnvironmentVariablesStringListCreator(r));
506
+
507
+ session = getApplicationPool()->get(options);
470
508
  P_TRACE(3, "Forwarding " << r->uri << " to PID " << session->getPid());
471
509
  } catch (const SpawnException &e) {
472
510
  r->status = 500;
@@ -500,34 +538,62 @@ private:
500
538
  sendRequestBody(r, session);
501
539
  }
502
540
  }
503
- session->shutdownWriter();
541
+ try {
542
+ session->shutdownWriter();
543
+ } catch (const SystemException &e) {
544
+ // Ignore ENOTCONN. This error occurs for some people
545
+ // for unknown reasons, but it's harmless.
546
+ if (e.code() != ENOTCONN) {
547
+ throw;
548
+ }
549
+ }
504
550
 
505
551
 
506
552
  /********** Step 4: forwarding the response from the backend
507
553
  process back to the HTTP client **********/
508
554
 
509
555
  UPDATE_TRACE_POINT();
510
- apr_file_t *readerPipe = NULL;
511
- int reader = session->getStream();
512
- pid_t backendPid = session->getPid();
513
- apr_os_pipe_put(&readerPipe, &reader, r->pool);
514
- apr_file_pipe_timeout_set(readerPipe, r->server->timeout);
515
-
556
+ apr_bucket_brigade *bb;
557
+ apr_bucket *b;
558
+ PassengerBucketStatePtr bucketState;
559
+ pid_t backendPid;
560
+
561
+ /* Setup the bucket brigade. */
562
+ bucketState = ptr(new PassengerBucketState());
516
563
  bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
517
- b = passenger_bucket_create(session, readerPipe, r->connection->bucket_alloc);
564
+ b = passenger_bucket_create(session, bucketState, r->connection->bucket_alloc);
565
+
566
+ /* The bucket (b) still has a reference to the session, so the reset()
567
+ * call here is guaranteed not to throw any exceptions.
568
+ */
569
+ backendPid = session->getPid();
518
570
  session.reset();
571
+
519
572
  APR_BRIGADE_INSERT_TAIL(bb, b);
520
573
 
521
574
  b = apr_bucket_eos_create(r->connection->bucket_alloc);
522
575
  APR_BRIGADE_INSERT_TAIL(bb, b);
523
576
 
524
- // I know the size because I read util_script.c's source. :-(
577
+ /* Now read the HTTP response header, parse it and fill relevant
578
+ * information in our request_rec structure.
579
+ */
580
+
581
+ /* I know the required size for backendData because I read
582
+ * util_script.c's source. :-(
583
+ */
525
584
  char backendData[MAX_STRING_LEN];
585
+ Timer timer;
526
586
  int result = ap_scan_script_header_err_brigade(r, bb, backendData);
587
+
527
588
  if (result == OK) {
528
589
  // The API documentation for ap_scan_script_err_brigade() says it
529
590
  // returns HTTP_OK on success, but it actually returns OK.
530
591
 
592
+ /* We were able to parse the HTTP response header sent by the
593
+ * backend process! Proceed with passing the bucket brigade,
594
+ * for forwarding the response body to the HTTP client.
595
+ */
596
+
531
597
  /* Manually set the Status header because
532
598
  * ap_scan_script_header_err_brigade() filters it
533
599
  * out. Some broken HTTP clients depend on the
@@ -540,17 +606,73 @@ private:
540
606
  }
541
607
  apr_table_setn(r->headers_out, "Status", r->status_line);
542
608
 
609
+ UPDATE_TRACE_POINT();
543
610
  ap_pass_brigade(r->output_filters, bb);
611
+
612
+ if (r->connection->aborted) {
613
+ P_WARN("The HTTP client closed the connection before "
614
+ "the response could be completely sent. As a "
615
+ "result, you will probably see a 'Broken Pipe' "
616
+ "error in this log file. Please ignore it, "
617
+ "this is normal.");
618
+ } else if (!bucketState->completed) {
619
+ P_WARN("Apache stopped forwarding the backend's response, "
620
+ "even though the HTTP client did not close the "
621
+ "connection. Is this an Apache bug?");
622
+ }
623
+
544
624
  return OK;
545
625
  } else if (backendData[0] == '\0') {
546
- P_ERROR("Backend process " << backendPid <<
547
- " did not return a valid HTTP response. It returned no data.");
626
+ if ((long long) timer.elapsed() >= r->server->timeout / 1000) {
627
+ // Looks like an I/O timeout.
628
+ P_ERROR("No data received from " <<
629
+ "the backend application (process " <<
630
+ backendPid << ") within " <<
631
+ (r->server->timeout / 1000) << " msec. Either " <<
632
+ "the backend application is frozen, or " <<
633
+ "your TimeOut value of " <<
634
+ (r->server->timeout / 1000000) <<
635
+ " seconds is too low. Please check " <<
636
+ "whether your application is frozen, or " <<
637
+ "increase the value of the TimeOut " <<
638
+ "configuration directive.");
639
+ } else {
640
+ P_ERROR("The backend application (process " <<
641
+ backendPid << ") did not send a valid " <<
642
+ "HTTP response; instead, it sent nothing " <<
643
+ "at all. It is possible that it has crashed; " <<
644
+ "please check whether there are crashing " <<
645
+ "bugs in this application.");
646
+ }
548
647
  apr_table_setn(r->err_headers_out, "Status", "500 Internal Server Error");
549
648
  return HTTP_INTERNAL_SERVER_ERROR;
550
649
  } else {
551
- P_ERROR("Backend process " << backendPid <<
552
- " did not return a valid HTTP response. It returned: [" <<
553
- backendData << "]");
650
+ if ((long long) timer.elapsed() >= r->server->timeout / 1000) {
651
+ // Looks like an I/O timeout.
652
+ P_ERROR("The backend application (process " <<
653
+ backendPid << ") hasn't sent a valid " <<
654
+ "HTTP response within " <<
655
+ (r->server->timeout / 1000) << " msec. Either " <<
656
+ "the backend application froze while " <<
657
+ "sending a response, or " <<
658
+ "your TimeOut value of " <<
659
+ (r->server->timeout / 1000000) <<
660
+ " seconds is too low. Please check " <<
661
+ "whether the application is frozen, or " <<
662
+ "increase the value of the TimeOut " <<
663
+ "configuration directive. The application " <<
664
+ "has sent this data so far: [" <<
665
+ backendData << "]");
666
+ } else {
667
+ P_ERROR("The backend application (process " <<
668
+ backendPid << ") didn't send a valid " <<
669
+ "HTTP response. It might have crashed " <<
670
+ "during the middle of sending an HTTP " <<
671
+ "response, so please check whether there " <<
672
+ "are crashing problems in your application. " <<
673
+ "This is the data that it sent: [" <<
674
+ backendData << "]");
675
+ }
554
676
  apr_table_setn(r->err_headers_out, "Status", "500 Internal Server Error");
555
677
  return HTTP_INTERNAL_SERVER_ERROR;
556
678
  }
@@ -668,16 +790,6 @@ private:
668
790
  }
669
791
  }
670
792
 
671
- // Add other environment variables.
672
- const apr_array_header_t *env_arr;
673
- apr_table_entry_t *env;
674
-
675
- env_arr = apr_table_elts(r->subprocess_env);
676
- env = (apr_table_entry_t*) env_arr->elts;
677
- for (i = 0; i < env_arr->nelts; ++i) {
678
- addHeader(headers, env[i].key, env[i].val);
679
- }
680
-
681
793
  // Now send the headers.
682
794
  string buffer;
683
795
 
@@ -721,6 +833,169 @@ private:
721
833
  return APR_SUCCESS;
722
834
  }
723
835
 
836
+ void throwUploadBufferingException(request_rec *r, int code) {
837
+ DirConfig *config = getDirConfig(r);
838
+ string message("An error occured while "
839
+ "buffering HTTP upload data to "
840
+ "a temporary file in ");
841
+ message.append(config->getUploadBufferDir());
842
+
843
+ switch (code) {
844
+ case ENOSPC:
845
+ message.append(". Disk directory doesn't have enough disk space, "
846
+ "so please make sure that it has "
847
+ "enough disk space for buffering file uploads, "
848
+ "or set the 'PassengerUploadBufferDir' directive "
849
+ "to a directory that has enough disk space.");
850
+ throw RuntimeException(message);
851
+ break;
852
+ case EDQUOT:
853
+ message.append(". The current Apache worker process (which is "
854
+ "running as ");
855
+ message.append(getProcessUsername());
856
+ message.append(") cannot write to this directory because of "
857
+ "disk quota limits. Please make sure that the volume "
858
+ "that this directory resides on has enough disk space "
859
+ "quota for the Apache worker process, or set the "
860
+ "'PassengerUploadBufferDir' directive to a different "
861
+ "directory that has enough disk space quota.");
862
+ throw RuntimeException(message);
863
+ break;
864
+ case ENOENT:
865
+ message.append(". This directory doesn't exist, so please make "
866
+ "sure that this directory exists, or set the "
867
+ "'PassengerUploadBufferDir' directive to a "
868
+ "directory that exists and can be written to.");
869
+ throw RuntimeException(message);
870
+ break;
871
+ case EACCES:
872
+ message.append(". The current Apache worker process (which is "
873
+ "running as ");
874
+ message.append(getProcessUsername());
875
+ message.append(") doesn't have permissions to write to this "
876
+ "directory. Please change the permissions for this "
877
+ "directory (as well as all parent directories) so that "
878
+ "it is writable by the Apache worker process, or set "
879
+ "the 'PassengerUploadBufferDir' directive to a directory "
880
+ "that Apache can write to.");
881
+ throw RuntimeException(message);
882
+ break;
883
+ default:
884
+ throw SystemException(message, code);
885
+ break;
886
+ }
887
+ }
888
+
889
+ /**
890
+ * Reads the next chunk of the request body and put it into a buffer.
891
+ *
892
+ * This is like ap_get_client_block(), but can actually report errors
893
+ * in a sane way. ap_get_client_block() tells you that something went
894
+ * wrong, but not *what* went wrong.
895
+ *
896
+ * @param r The current request.
897
+ * @param buffer A buffer to put the read data into.
898
+ * @param bufsiz The size of the buffer.
899
+ * @return The number of bytes read, or 0 on EOF.
900
+ * @throws RuntimeException Something non-I/O related went wrong, e.g.
901
+ * failure to allocate memory and stuff.
902
+ * @throws IOException An I/O error occurred while trying to read the
903
+ * request body data.
904
+ */
905
+ unsigned long readRequestBodyFromApache(request_rec *r, char *buffer, apr_size_t bufsiz) {
906
+ apr_status_t rv;
907
+ apr_bucket_brigade *bb;
908
+
909
+ if (r->remaining < 0 || (!r->read_chunked && r->remaining == 0)) {
910
+ return 0;
911
+ }
912
+
913
+ bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
914
+ if (bb == NULL) {
915
+ r->connection->keepalive = AP_CONN_CLOSE;
916
+ throw RuntimeException("An error occurred while receiving HTTP upload data: "
917
+ "unable to create a bucket brigade. Maybe the system doesn't have "
918
+ "enough free memory.");
919
+ }
920
+
921
+ rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
922
+ APR_BLOCK_READ, bufsiz);
923
+
924
+ /* We lose the failure code here. This is why ap_get_client_block should
925
+ * not be used.
926
+ */
927
+ if (rv != APR_SUCCESS) {
928
+ /* if we actually fail here, we want to just return and
929
+ * stop trying to read data from the client.
930
+ */
931
+ r->connection->keepalive = AP_CONN_CLOSE;
932
+ apr_brigade_destroy(bb);
933
+
934
+ char buf[150], *errorString, message[1024];
935
+ errorString = apr_strerror(rv, buf, sizeof(buf));
936
+ if (errorString != NULL) {
937
+ snprintf(message, sizeof(message),
938
+ "An error occurred while receiving HTTP upload data: %s (%d)",
939
+ errorString, rv);
940
+ } else {
941
+ snprintf(message, sizeof(message),
942
+ "An error occurred while receiving HTTP upload data: unknown error %d",
943
+ rv);
944
+ }
945
+ message[sizeof(message) - 1] = '\0';
946
+ throw RuntimeException(message);
947
+ }
948
+
949
+ /* If this fails, it means that a filter is written incorrectly and that
950
+ * it needs to learn how to properly handle APR_BLOCK_READ requests by
951
+ * returning data when requested.
952
+ */
953
+ if (APR_BRIGADE_EMPTY(bb)) {
954
+ throw RuntimeException("An error occurred while receiving HTTP upload data: "
955
+ "the next filter in the input filter chain has "
956
+ "a bug. Please contact the author who wrote this filter about "
957
+ "this. This problem is not caused by Phusion Passenger.");
958
+ }
959
+
960
+ /* Check to see if EOS in the brigade.
961
+ *
962
+ * If so, we have to leave a nugget for the *next* readRequestBodyFromApache()
963
+ * call to return 0.
964
+ */
965
+ if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
966
+ if (r->read_chunked) {
967
+ r->remaining = -1;
968
+ } else {
969
+ r->remaining = 0;
970
+ }
971
+ }
972
+
973
+ rv = apr_brigade_flatten(bb, buffer, &bufsiz);
974
+ if (rv != APR_SUCCESS) {
975
+ apr_brigade_destroy(bb);
976
+
977
+ char buf[150], *errorString, message[1024];
978
+ errorString = apr_strerror(rv, buf, sizeof(buf));
979
+ if (errorString != NULL) {
980
+ snprintf(message, sizeof(message),
981
+ "An error occurred while receiving HTTP upload data: %s (%d)",
982
+ errorString, rv);
983
+ } else {
984
+ snprintf(message, sizeof(message),
985
+ "An error occurred while receiving HTTP upload data: unknown error %d",
986
+ rv);
987
+ }
988
+ message[sizeof(message) - 1] = '\0';
989
+ throw IOException(message);
990
+ }
991
+
992
+ /* XXX yank me? */
993
+ r->read_length += bufsiz;
994
+
995
+ apr_brigade_destroy(bb);
996
+ return bufsiz;
997
+ }
998
+
724
999
  /**
725
1000
  * Receive the HTTP upload data and buffer it into a BufferedUpload temp file.
726
1001
  *
@@ -729,44 +1004,35 @@ private:
729
1004
  * to check whether the HTTP client has sent complete upload
730
1005
  * data. NULL indicates that there is no Content-Length header,
731
1006
  * i.e. that the HTTP client used chunked transfer encoding.
1007
+ * @throws RuntimeException
1008
+ * @throws SystemException
1009
+ * @throws IOException
732
1010
  */
733
1011
  shared_ptr<BufferedUpload> receiveRequestBody(request_rec *r, const char *contentLength) {
734
1012
  TRACE_POINT();
735
- shared_ptr<BufferedUpload> tempFile(new BufferedUpload());
1013
+ DirConfig *config = getDirConfig(r);
1014
+ shared_ptr<BufferedUpload> tempFile;
1015
+ try {
1016
+ tempFile.reset(new BufferedUpload(config->getUploadBufferDir()));
1017
+ } catch (const SystemException &e) {
1018
+ throwUploadBufferingException(r, e.code());
1019
+ }
1020
+
736
1021
  char buf[1024 * 32];
737
1022
  apr_off_t len;
738
1023
  size_t total_written = 0;
739
1024
 
740
- while ((len = ap_get_client_block(r, buf, sizeof(buf))) > 0) {
1025
+ while ((len = readRequestBodyFromApache(r, buf, sizeof(buf))) > 0) {
741
1026
  size_t written = 0;
742
1027
  do {
743
1028
  size_t ret = fwrite(buf, 1, len - written, tempFile->handle);
744
1029
  if (ret <= 0 || fflush(tempFile->handle) == EOF) {
745
- int e = errno;
746
- string message("An error occured while "
747
- "buffering HTTP upload data to "
748
- "a temporary file in ");
749
- message.append(BufferedUpload::getDir());
750
- if (e == ENOSPC) {
751
- message.append(". Please make sure "
752
- "that this directory has "
753
- "enough disk space for "
754
- "buffering file uploads, "
755
- "or set the 'PassengerTempDir' "
756
- "directive to a directory "
757
- "that has enough disk space.");
758
- throw RuntimeException(message);
759
- } else {
760
- throw SystemException(message, e);
761
- }
1030
+ throwUploadBufferingException(r, errno);
762
1031
  }
763
1032
  written += ret;
764
1033
  } while (written < (size_t) len);
765
1034
  total_written += written;
766
1035
  }
767
- if (len == -1) {
768
- throw IOException("An error occurred while receiving HTTP upload data.");
769
- }
770
1036
 
771
1037
  if (contentLength != NULL && ftell(tempFile->handle) != atol(contentLength)) {
772
1038
  throw IOException("The HTTP client sent incomplete upload data.");
@@ -791,23 +1057,20 @@ private:
791
1057
  char buf[1024 * 32];
792
1058
  apr_off_t len;
793
1059
 
794
- while ((len = ap_get_client_block(r, buf, sizeof(buf))) > 0) {
1060
+ while ((len = readRequestBodyFromApache(r, buf, sizeof(buf))) > 0) {
795
1061
  session->sendBodyBlock(buf, len);
796
1062
  }
797
- if (len == -1) {
798
- throw IOException("An error occurred while receiving HTTP upload data.");
799
- }
800
1063
  }
801
1064
 
802
1065
  public:
803
- Hooks(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) {
1066
+ Hooks(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
1067
+ : cstat(1024) {
804
1068
  passenger_config_merge_all_servers(pconf, s);
805
1069
  ServerConfig *config = getServerConfig(s);
806
1070
  Passenger::setLogLevel(config->logLevel);
807
1071
  m_hasModRewrite = UNKNOWN;
808
1072
  m_hasModDir = UNKNOWN;
809
1073
  m_hasModAutoIndex = UNKNOWN;
810
- mstat = cached_multi_file_stat_new(1024);
811
1074
 
812
1075
  P_DEBUG("Initializing Phusion Passenger...");
813
1076
  ap_add_version_component(pconf, "Phusion_Passenger/" PASSENGER_VERSION);
@@ -823,11 +1086,9 @@ public:
823
1086
  * of the process in which the Hooks constructor was called for
824
1087
  * the second time.
825
1088
  */
826
- unsetenv("TMPDIR");
827
1089
  createPassengerTempDir(config->getTempDir(), config->userSwitching,
828
1090
  config->getDefaultUser(), unixd_config.user_id,
829
1091
  unixd_config.group_id);
830
- setenv("TMPDIR", (getPassengerTempDir() + "/var").c_str(), 1);
831
1092
 
832
1093
  ruby = (config->ruby != NULL) ? config->ruby : DEFAULT_RUBY_COMMAND;
833
1094
  if (config->userSwitching) {
@@ -873,7 +1134,6 @@ public:
873
1134
  }
874
1135
 
875
1136
  ~Hooks() {
876
- cached_multi_file_stat_free(mstat);
877
1137
  removeDirTree(getPassengerTempDir().c_str());
878
1138
  }
879
1139