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/Version.h CHANGED
@@ -26,6 +26,6 @@
26
26
  #define _PASSENGER_VERSION_H_
27
27
 
28
28
  /* Don't forget to update lib/phusion_passenger/constants.rb too. */
29
- #define PASSENGER_VERSION "2.2.2"
29
+ #define PASSENGER_VERSION "2.2.3"
30
30
 
31
31
  #endif /* _PASSENGER_VERSION_H */
@@ -83,10 +83,6 @@ passenger_init_main_conf(ngx_conf_t *cf, void *conf_pointer)
83
83
  conf = &passenger_main_conf;
84
84
  *conf = *((passenger_main_conf_t *) conf_pointer);
85
85
 
86
- if (conf->root_dir.len == 0) {
87
- return "-- The 'passenger_root' directive must be set";
88
- }
89
-
90
86
  if (conf->ruby.len == 0) {
91
87
  conf->ruby.data = (u_char *) "ruby";
92
88
  conf->ruby.len = sizeof("ruby") - 1;
@@ -63,10 +63,10 @@ get_file_type(const u_char *filename, unsigned int throttle_rate) {
63
63
  struct stat buf;
64
64
  int ret;
65
65
 
66
- ret = cached_multi_file_stat_perform(passenger_stat_cache,
67
- (const char *) filename,
68
- &buf,
69
- throttle_rate);
66
+ ret = cached_file_stat_perform(passenger_stat_cache,
67
+ (const char *) filename,
68
+ &buf,
69
+ throttle_rate);
70
70
  if (ret == 0) {
71
71
  if (S_ISREG(buf.st_mode)) {
72
72
  return FT_FILE;
@@ -105,7 +105,7 @@ detect_application_type(const ngx_str_t *public_dir) {
105
105
 
106
106
  ngx_memzero(filename, sizeof(filename));
107
107
  ngx_snprintf(filename, sizeof(filename), "%s/%s",
108
- public_dir->data, "../config/passenger_wsgi.py");
108
+ public_dir->data, "../passenger_wsgi.py");
109
109
  if (file_exists(filename, 1)) {
110
110
  return AP_WSGI;
111
111
  }
@@ -1077,7 +1077,9 @@ passenger_content_handler(ngx_http_request_t *r)
1077
1077
  ngx_str_t page_cache_file;
1078
1078
  passenger_context_t *context;
1079
1079
 
1080
- if (r->subrequest_in_memory) {
1080
+ if (passenger_main_conf.root_dir.len == 0) {
1081
+ return NGX_DECLINED;
1082
+ } else if (r->subrequest_in_memory) {
1081
1083
  ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1082
1084
  "ngx_http_passenger_module does not support "
1083
1085
  "subrequest in memory");
@@ -122,6 +122,8 @@ public:
122
122
  }
123
123
  };
124
124
 
125
+ struct ClientDisconnectedException { };
126
+
125
127
  /**
126
128
  * A representation of a Client from the Server's point of view. This class
127
129
  * contains the methods used to communicate from a server to a connected
@@ -311,7 +313,12 @@ private:
311
313
  *
312
314
  * @param session The Ruby on Rails session to read the response from.
313
315
  * @param clientFd The client file descriptor to write the response to.
314
- * @throws SystemException Response could not be read from backend (Rails) process.
316
+ * @throws SystemException Something went wrong while reading the response
317
+ * from the backend process or while writing to the
318
+ * response back to the web server.
319
+ * @throws ClientDisconnectedException The HTTP client closed the connection
320
+ * before we were able to send back the
321
+ * full response.
315
322
  */
316
323
  void forwardResponse(Application::SessionPtr &session, FileDescriptor &clientFd) {
317
324
  TRACE_POINT();
@@ -339,13 +346,21 @@ private:
339
346
  * of the response data.
340
347
  */
341
348
  UPDATE_TRACE_POINT();
342
- string statusLine("HTTP/1.1 ");
343
- statusLine.append(ex.getStatusLine());
344
- UPDATE_TRACE_POINT();
345
- output.writeRaw(statusLine.c_str(), statusLine.size());
346
- UPDATE_TRACE_POINT();
347
- output.writeRaw(ex.getBuffer().c_str(), ex.getBuffer().size());
348
- break;
349
+ try {
350
+ string statusLine("HTTP/1.1 ");
351
+ statusLine.append(ex.getStatusLine());
352
+ UPDATE_TRACE_POINT();
353
+ output.writeRaw(statusLine.c_str(), statusLine.size());
354
+ UPDATE_TRACE_POINT();
355
+ output.writeRaw(ex.getBuffer().c_str(), ex.getBuffer().size());
356
+ break;
357
+ } catch (const SystemException &e) {
358
+ if (e.code() == EPIPE) {
359
+ throw ClientDisconnectedException();
360
+ } else {
361
+ throw;
362
+ }
363
+ }
349
364
  }
350
365
  }
351
366
 
@@ -359,7 +374,15 @@ private:
359
374
  throw SystemException("Cannot read response from backend process", errno);
360
375
  } else {
361
376
  UPDATE_TRACE_POINT();
362
- output.writeRaw(buf, size);
377
+ try {
378
+ output.writeRaw(buf, size);
379
+ } catch (const SystemException &e) {
380
+ if (e.code() == EPIPE) {
381
+ throw ClientDisconnectedException();
382
+ } else {
383
+ throw;
384
+ }
385
+ }
363
386
  }
364
387
  }
365
388
  }
@@ -399,10 +422,8 @@ private:
399
422
  * Handles an SCGI request from a client whose identity is derived by the given <tt>clientFd</tt>.
400
423
  *
401
424
  * @param clientFd The file descriptor identifying the client to handle the request from.
402
- * @return True if an error occurred while trying to handle the request of the client. False if
403
- * the request was succesfully processed.
404
425
  */
405
- bool handleRequest(FileDescriptor &clientFd) {
426
+ void handleRequest(FileDescriptor &clientFd) {
406
427
  TRACE_POINT();
407
428
  ScgiRequestParser parser;
408
429
  string partialRequestBody;
@@ -410,18 +431,19 @@ private:
410
431
 
411
432
  if (!readAndCheckPassword(clientFd)) {
412
433
  P_ERROR("Client did not send a correct password.");
413
- return true;
434
+ return;
414
435
  }
415
436
  if (!readAndParseRequestHeaders(clientFd, parser, partialRequestBody)) {
416
- return true;
437
+ return;
417
438
  }
418
439
 
419
440
  try {
420
441
  PoolOptions options;
421
- if (parser.getHeader("RAILS_RELATIVE_URL_ROOT").empty()) {
442
+ if (parser.getHeader("SCRIPT_NAME").empty()) {
422
443
  options.appRoot = extractDirName(parser.getHeader("DOCUMENT_ROOT"));
423
444
  } else {
424
445
  options.appRoot = extractDirName(resolveSymlink(parser.getHeader("DOCUMENT_ROOT")));
446
+ options.baseURI = parser.getHeader("SCRIPT_NAME");
425
447
  }
426
448
  options.useGlobalQueue = parser.getHeader("PASSENGER_USE_GLOBAL_QUEUE") == "true";
427
449
  options.environment = parser.getHeader("PASSENGER_ENVIRONMENT");
@@ -450,23 +472,23 @@ private:
450
472
  forwardResponse(session, clientFd);
451
473
  } catch (const SpawnException &e) {
452
474
  handleSpawnException(clientFd, e);
475
+ } catch (const ClientDisconnectedException &) {
476
+ P_WARN("Couldn't forward the HTTP response back to the HTTP client: "
477
+ "It seems the user clicked on the 'Stop' button in his "
478
+ "browser.");
453
479
  }
454
- return false;
455
480
  } catch (const boost::thread_interrupted &) {
456
481
  throw;
457
482
  } catch (const tracable_exception &e) {
458
483
  P_ERROR("Uncaught exception in PassengerServer client thread:\n"
459
484
  << " exception: " << e.what() << "\n"
460
485
  << " backtrace:\n" << e.backtrace());
461
- return true;
462
486
  } catch (const exception &e) {
463
487
  P_ERROR("Uncaught exception in PassengerServer client thread:\n"
464
488
  << " exception: " << e.what() << "\n"
465
489
  << " backtrace: not available");
466
- return true;
467
490
  } catch (...) {
468
491
  P_ERROR("Uncaught unknown exception in PassengerServer client thread.");
469
- return true;
470
492
  }
471
493
  }
472
494
 
@@ -555,8 +577,6 @@ typedef shared_ptr<Client> ClientPtr;
555
577
  */
556
578
  class Server {
557
579
  private:
558
- static const unsigned int BACKLOG_SIZE = 50;
559
-
560
580
  string password;
561
581
  int adminPipe;
562
582
  int serverSocket;
@@ -573,45 +593,15 @@ private:
573
593
  * attempt to bind on. Once it is bound, it will start listening for incoming client
574
594
  * activity.
575
595
  *
576
- * @throws SystemException Could not create unconnected Unix socket or bind on Unix socket.
596
+ * @throws SystemException Something went wrong while trying to create and bind to the Unix socket.
597
+ * @throws RuntimeException Something went wrong.
577
598
  */
578
599
  void startListening() {
579
600
  this_thread::disable_syscall_interruption dsi;
580
601
  string socketName = getPassengerTempDir() + "/master/helper_server.sock";
581
- struct sockaddr_un addr;
582
- int ret;
583
-
584
- serverSocket = syscalls::socket(PF_UNIX, SOCK_STREAM, 0);
585
- if (serverSocket == -1) {
586
- throw SystemException("Cannot create an unconnected Unix socket", errno);
587
- }
588
-
589
- addr.sun_family = AF_UNIX;
590
- strncpy(addr.sun_path, socketName.c_str(), sizeof(addr.sun_path));
591
- addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
592
-
593
- ret = syscalls::bind(serverSocket, (const struct sockaddr *) &addr, sizeof(addr));
594
- if (ret == -1) {
595
- int e = errno;
596
- syscalls::close(serverSocket);
597
-
598
- string message("Cannot bind on Unix socket '");
599
- message.append(socketName);
600
- message.append("'");
601
- throw SystemException(message, e);
602
- }
603
-
604
- ret = syscalls::listen(serverSocket, BACKLOG_SIZE);
605
- if (ret == -1) {
606
- int e = errno;
607
- syscalls::close(serverSocket);
608
-
609
- string message("Cannot bind on Unix socket '");
610
- message.append(socketName);
611
- message.append("'");
612
- throw SystemException(message, e);
613
- }
602
+ serverSocket = createUnixServer(socketName.c_str());
614
603
 
604
+ int ret;
615
605
  do {
616
606
  ret = chmod(socketName.c_str(), S_ISVTX |
617
607
  S_IRUSR | S_IWUSR | S_IXUSR |
@@ -159,6 +159,10 @@ private:
159
159
  case 307:
160
160
  statusLine = "307 Temporary Redirect\x0D\x0A";
161
161
  break;
162
+ case 308:
163
+ // Google Gears: http://code.google.com/p/gears/wiki/ResumableHttpRequestsProposal
164
+ statusLine = "308 Resume Incomplete\x0D\x0A";
165
+ break;
162
166
  case 400:
163
167
  statusLine = "400 Bad Request\x0D\x0A";
164
168
  break;
@@ -26,6 +26,25 @@
26
26
 
27
27
  #include "StaticContentHandler.h"
28
28
 
29
+ static void
30
+ set_request_extension(ngx_http_request_t *r, ngx_str_t *filename) {
31
+ u_char *tmp;
32
+
33
+ /* Scan filename from the right until we've found a slash or a dot. */
34
+ tmp = filename->data + filename->len - 1;
35
+ while (tmp >= filename->data && *tmp != '/' && *tmp != '.') {
36
+ tmp--;
37
+ }
38
+ if (tmp >= filename->data && *tmp == '.') {
39
+ /* We found a dot, and until now we haven't seen any slashes.
40
+ * So we know that this is the filename's extension.
41
+ */
42
+ tmp++;
43
+ r->exten.data = tmp;
44
+ r->exten.len = filename->len - (tmp - filename->data);
45
+ }
46
+ }
47
+
29
48
  ngx_int_t
30
49
  passenger_static_content_handler(ngx_http_request_t *r, ngx_str_t *filename)
31
50
  {
@@ -58,10 +77,10 @@ passenger_static_content_handler(ngx_http_request_t *r, ngx_str_t *filename)
58
77
 
59
78
  clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
60
79
 
61
- #if NGX_VERSION_NUM < 7000
80
+ ngx_memzero(&of, sizeof(ngx_open_file_info_t));
81
+ #if NGINX_VERSION_NUM < 7000
62
82
  of.test_dir = 0;
63
83
  #else
64
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
65
84
  of.directio = clcf->directio;
66
85
  #endif
67
86
  of.valid = clcf->open_file_cache_valid;
@@ -106,7 +125,7 @@ passenger_static_content_handler(ngx_http_request_t *r, ngx_str_t *filename)
106
125
  return rc;
107
126
  }
108
127
 
109
- #if NGX_VERSION_NUM >= 7000
128
+ #if NGINX_VERSION_NUM >= 7000
110
129
  r->root_tested = !r->error_page;
111
130
  #endif
112
131
 
@@ -131,7 +150,7 @@ passenger_static_content_handler(ngx_http_request_t *r, ngx_str_t *filename)
131
150
  len += r->args.len + 1;
132
151
  }
133
152
 
134
- #if NGX_VERSION_NUM < 7000
153
+ #if NGINX_VERSION_NUM < 7000
135
154
  location = ngx_palloc(r->pool, len);
136
155
  #else
137
156
  location = ngx_pnalloc(r->pool, len);
@@ -188,6 +207,7 @@ passenger_static_content_handler(ngx_http_request_t *r, ngx_str_t *filename)
188
207
  r->headers_out.content_length_n = of.size;
189
208
  r->headers_out.last_modified_time = of.mtime;
190
209
 
210
+ set_request_extension(r, filename);
191
211
  if (ngx_http_set_content_type(r) != NGX_OK) {
192
212
  return NGX_HTTP_INTERNAL_SERVER_ERROR;
193
213
  }
@@ -226,7 +246,7 @@ passenger_static_content_handler(ngx_http_request_t *r, ngx_str_t *filename)
226
246
  b->file->fd = of.fd;
227
247
  b->file->name = *filename;
228
248
  b->file->log = log;
229
- #if NGX_VERSION_NUM >= 7000
249
+ #if NGINX_VERSION_NUM >= 7000
230
250
  b->file->directio = of.is_directio;
231
251
  #endif
232
252
 
data/ext/nginx/config CHANGED
@@ -26,6 +26,9 @@ CORE_LIBS="$CORE_LIBS \
26
26
  ${ngx_addon_dir}/libpassenger_common.a \
27
27
  ${ngx_addon_dir}/libboost_oxt.a \
28
28
  -lstdc++ -lpthread"
29
+ if test x`uname` = xOpenBSD; then
30
+ CORE_LIBS="$CORE_LIBS -lm"
31
+ fi
29
32
 
30
33
  nginx_version=`grep 'NGINX_VERSION ' src/core/nginx.h | awk '{ print $3 }' | sed 's/"//g'`
31
34
 
@@ -54,11 +54,18 @@ static ngx_str_t ngx_http_scgi_script_name = ngx_string("scgi_script_name");
54
54
  static pid_t helper_server_pid = 0;
55
55
  static int helper_server_admin_pipe;
56
56
  static u_char helper_server_password_data[HELPER_SERVER_PASSWORD_SIZE];
57
+ /** perl_module destroys the original environment variables for some reason,
58
+ * so when we get a SIGHUP (for restarting Nginx) $TMPDIR might not have the
59
+ * same value as it had during Nginx startup. We need the original $TMPDIR
60
+ * value for calculating the Passenger temp dir location, so here we cache
61
+ * the original value instead of getenv()'ing it every time.
62
+ */
63
+ const char *system_temp_dir = NULL;
57
64
  const char passenger_temp_dir[NGX_MAX_PATH];
58
65
  ngx_str_t passenger_schema_string;
59
66
  ngx_str_t passenger_helper_server_password;
60
67
  const char passenger_helper_server_socket[NGX_MAX_PATH];
61
- CachedMultiFileStat *passenger_stat_cache;
68
+ CachedFileStat *passenger_stat_cache;
62
69
 
63
70
  static void shutdown_helper_server(ngx_cycle_t *cycle);
64
71
 
@@ -122,10 +129,17 @@ start_helper_server(ngx_cycle_t *cycle)
122
129
  long i;
123
130
  ssize_t ret;
124
131
  char buf;
125
- FILE *f;
132
+ ngx_str_t *log_filename;
133
+ FILE *f, *log_file;
134
+
135
+ shutdown_helper_server(cycle);
126
136
 
127
- if (helper_server_pid != 0) {
128
- shutdown_helper_server(cycle);
137
+ if (main_conf->root_dir.len == 0) {
138
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
139
+ "Phusion Passenger is disabled because the "
140
+ "'passenger_root' option is not set. Please set "
141
+ "this option if you want to enable Phusion Passenger.");
142
+ return NGX_OK;
129
143
  }
130
144
 
131
145
  ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
@@ -219,10 +233,35 @@ start_helper_server(ngx_cycle_t *cycle)
219
233
  close(admin_pipe[1]);
220
234
  close(feedback_pipe[0]);
221
235
 
222
- /* Nginx redirects stderr to the error log file. Make sure that
223
- * stdout is redirected to the error log file as well.
236
+ /* At this point, stdout and stderr may still point to the console.
237
+ * Make sure that they're both redirected to the log file.
224
238
  */
225
- dup2(2, 1);
239
+ log_file = NULL;
240
+ #if NGINX_VERSION_NUM < 7000
241
+ log_filename = &cycle->new_log->file->name;
242
+ #else
243
+ log_filename = &cycle->new_log.file->name;
244
+ #endif
245
+ if (log_filename->len > 0) {
246
+ log_file = fopen((const char *) log_filename->data, "a");
247
+ if (log_file == NULL) {
248
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
249
+ "could not open the error log file for writing");
250
+ }
251
+ }
252
+ if (log_file == NULL) {
253
+ /* If the log file cannot be opened then we redirect stdout
254
+ * and stderr to /dev/null, because if the user disconnects
255
+ * from the console on which Nginx is started, then on Linux
256
+ * any writes to stdout or stderr will result in an EIO error.
257
+ */
258
+ log_file = fopen("/dev/null", "w");
259
+ }
260
+ if (log_file != NULL) {
261
+ dup2(fileno(log_file), 1);
262
+ dup2(fileno(log_file), 2);
263
+ fclose(log_file);
264
+ }
226
265
 
227
266
  /* Close all file descriptors except stdin, stdout, stderr and
228
267
  * the reader part of the pipe we just created.
@@ -241,6 +280,8 @@ start_helper_server(ngx_cycle_t *cycle)
241
280
  close(i);
242
281
  }
243
282
 
283
+ setenv("SERVER_SOFTWARE", NGINX_VER, 1);
284
+
244
285
  execlp((const char *) helper_server_filename,
245
286
  "PassengerNginxHelperServer",
246
287
  main_conf->root_dir.data,
@@ -256,7 +297,7 @@ start_helper_server(ngx_cycle_t *cycle)
256
297
  worker_uid_string,
257
298
  worker_gid_string,
258
299
  passenger_temp_dir,
259
- NULL);
300
+ (char *) 0);
260
301
  e = errno;
261
302
  fprintf(stderr, "*** Could not start the Passenger helper server (%s): "
262
303
  "exec() failed: %s (%d)\n",
@@ -357,6 +398,10 @@ save_master_process_pid(ngx_cycle_t *cycle) {
357
398
  u_char *last;
358
399
  FILE *f;
359
400
 
401
+ if (passenger_main_conf.root_dir.len == 0) {
402
+ return NGX_OK;
403
+ }
404
+
360
405
  last = ngx_snprintf(filename, sizeof(filename) - 1,
361
406
  "%s/control_process.pid", passenger_temp_dir);
362
407
  *last = (u_char) '\0';
@@ -380,6 +425,10 @@ shutdown_helper_server(ngx_cycle_t *cycle)
380
425
  int helper_server_exited, ret;
381
426
  u_char command[NGX_MAX_PATH + 10];
382
427
 
428
+ if (helper_server_pid == 0) {
429
+ return;
430
+ }
431
+
383
432
  /* We write one byte to the admin pipe, doesn't matter what the byte is.
384
433
  * The helper server will detect this as an exit command.
385
434
  */
@@ -442,7 +491,6 @@ shutdown_helper_server(ngx_cycle_t *cycle)
442
491
  passenger_temp_dir);
443
492
  }
444
493
  }
445
-
446
494
  helper_server_pid = 0;
447
495
  }
448
496
 
@@ -509,15 +557,15 @@ static ngx_int_t
509
557
  pre_config_init(ngx_conf_t *cf)
510
558
  {
511
559
  ngx_int_t ret;
512
- const char *system_temp_dir;
513
560
  u_char command[NGX_MAX_PATH + 30];
561
+ u_char *last;
514
562
 
515
563
  ngx_memzero(&passenger_main_conf, sizeof(passenger_main_conf_t));
516
564
 
517
565
  passenger_schema_string.data = (u_char *) "passenger://";
518
566
  passenger_schema_string.len = sizeof("passenger://") - 1;
519
567
 
520
- passenger_stat_cache = cached_multi_file_stat_new(1024);
568
+ passenger_stat_cache = cached_file_stat_new(1024);
521
569
 
522
570
  ret = add_variables(cf);
523
571
  if (ret != NGX_OK) {
@@ -526,9 +574,13 @@ pre_config_init(ngx_conf_t *cf)
526
574
 
527
575
  /* Setup Passenger temp folder. */
528
576
 
529
- system_temp_dir = getenv("TMPDIR");
530
- if (!system_temp_dir || !*system_temp_dir) {
531
- system_temp_dir = "/tmp";
577
+ if (system_temp_dir == NULL) {
578
+ const char *tmp = getenv("TMPDIR");
579
+ if (tmp == NULL || *tmp == '\0') {
580
+ system_temp_dir = "/tmp";
581
+ } else {
582
+ system_temp_dir = strdup(tmp);
583
+ }
532
584
  }
533
585
 
534
586
  ngx_memzero(&passenger_temp_dir, sizeof(passenger_temp_dir));
@@ -554,13 +606,16 @@ pre_config_init(ngx_conf_t *cf)
554
606
 
555
607
  /* Build helper server socket filename string. */
556
608
 
557
- if (ngx_snprintf((u_char *) passenger_helper_server_socket, NGX_MAX_PATH,
558
- "unix:%s/master/helper_server.sock",
559
- passenger_temp_dir) == NULL) {
609
+ last = ngx_snprintf((u_char *) passenger_helper_server_socket, NGX_MAX_PATH,
610
+ "unix:%s/master/helper_server.sock",
611
+ passenger_temp_dir);
612
+ if (last == NULL) {
560
613
  ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
561
614
  "could not create Passenger helper server "
562
615
  "socket filename string");
563
616
  return NGX_ERROR;
617
+ } else {
618
+ *last = (u_char) '\0';
564
619
  }
565
620
 
566
621
  return NGX_OK;