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.
- data/DEVELOPERS.TXT +13 -3
- data/Rakefile +42 -33
- data/bin/passenger-install-apache2-module +1 -2
- data/bin/passenger-install-nginx-module +7 -19
- data/bin/passenger-status +64 -15
- data/bin/passenger-stress-test +2 -2
- data/doc/ApplicationPool algorithm.txt +26 -22
- data/doc/Users guide Apache.html +374 -149
- data/doc/Users guide Apache.txt +318 -51
- data/doc/Users guide Nginx.html +13 -13
- data/doc/Users guide Nginx.txt +7 -2
- data/doc/cxxapi/Bucket_8h-source.html +62 -25
- data/doc/cxxapi/Configuration_8h-source.html +343 -326
- data/doc/cxxapi/DirectoryMapper_8h-source.html +12 -12
- data/doc/cxxapi/Hooks_8h-source.html +1 -1
- data/doc/cxxapi/annotated.html +1 -1
- data/doc/cxxapi/classHooks-members.html +1 -1
- data/doc/cxxapi/classHooks.html +1 -1
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +2 -2
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +9 -9
- data/doc/cxxapi/classes.html +1 -1
- data/doc/cxxapi/definitions_8h-source.html +1 -1
- data/doc/cxxapi/files.html +1 -1
- data/doc/cxxapi/functions.html +2 -2
- data/doc/cxxapi/functions_func.html +2 -2
- data/doc/cxxapi/graph_legend.html +1 -1
- data/doc/cxxapi/group__Configuration.html +1 -1
- data/doc/cxxapi/group__Core.html +1 -1
- data/doc/cxxapi/group__Hooks.html +1 -1
- data/doc/cxxapi/group__Support.html +1 -1
- data/doc/cxxapi/main.html +1 -1
- data/doc/cxxapi/modules.html +1 -1
- data/doc/rdoc/classes/ConditionVariable.html +194 -0
- data/doc/rdoc/classes/Exception.html +120 -0
- data/doc/rdoc/classes/GC.html +113 -0
- data/doc/rdoc/classes/IO.html +169 -0
- data/doc/rdoc/classes/PhusionPassenger.html +238 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +153 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +517 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +719 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +97 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +96 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +97 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +96 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +598 -0
- data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +140 -0
- data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +317 -0
- data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +138 -0
- data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +154 -0
- data/doc/rdoc/classes/PhusionPassenger/Application.html +283 -0
- data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +172 -0
- data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +145 -0
- data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +175 -0
- data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +141 -0
- data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +92 -0
- data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +489 -0
- data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +350 -0
- data/doc/rdoc/classes/PhusionPassenger/Rack.html +91 -0
- data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +188 -0
- data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +194 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz.html +95 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +442 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +98 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +200 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +436 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +98 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +155 -0
- data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +402 -0
- data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +125 -0
- data/doc/rdoc/classes/PhusionPassenger/Utils.html +805 -0
- data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +140 -0
- data/doc/rdoc/classes/PhusionPassenger/WSGI.html +89 -0
- data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +188 -0
- data/doc/rdoc/classes/PlatformInfo.html +831 -0
- data/doc/rdoc/classes/RakeExtensions.html +197 -0
- data/doc/rdoc/classes/Signal.html +131 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/DEVELOPERS_TXT.html +255 -0
- data/doc/rdoc/files/README.html +157 -0
- data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +92 -0
- data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +129 -0
- data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +131 -0
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +126 -0
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +130 -0
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +130 -0
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +127 -0
- data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +126 -0
- data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +134 -0
- data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +126 -0
- data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +127 -0
- data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +133 -0
- data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +127 -0
- data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +143 -0
- data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +126 -0
- data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +145 -0
- data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +127 -0
- data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +161 -0
- data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +175 -0
- data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +129 -0
- data/doc/rdoc/files/misc/rake/extensions_rb.html +130 -0
- data/doc/rdoc/fr_class_index.html +90 -0
- data/doc/rdoc/fr_file_index.html +76 -0
- data/doc/rdoc/fr_method_index.html +200 -0
- data/doc/rdoc/index.html +26 -0
- data/doc/rdoc/rdoc-style.css +187 -0
- data/doc/users_guide_snippets/rackup_specifications.txt +2 -8
- data/ext/apache2/Bucket.cpp +71 -38
- data/ext/apache2/Bucket.h +53 -16
- data/ext/apache2/Configuration.cpp +15 -0
- data/ext/apache2/Configuration.h +19 -2
- data/ext/apache2/DirectoryMapper.h +10 -10
- data/ext/apache2/Hooks.cpp +334 -74
- data/ext/boost/mpl/apply.hpp +5 -1
- data/ext/boost/mpl/apply_wrap.hpp +5 -2
- data/ext/boost/mpl/aux_/full_lambda.hpp +5 -1
- data/ext/boost/mpl/bind.hpp +5 -1
- data/ext/common/Application.h +11 -31
- data/ext/common/ApplicationPool.h +2 -1
- data/ext/common/ApplicationPoolServer.h +61 -20
- data/ext/common/ApplicationPoolServerExecutable.cpp +132 -4
- data/ext/common/ApplicationPoolStatusReporter.h +189 -65
- data/ext/common/Base64.cpp +143 -0
- data/ext/common/Base64.h +57 -0
- data/ext/common/CachedFileStat.cpp +25 -82
- data/ext/common/CachedFileStat.h +11 -125
- data/ext/common/CachedFileStat.hpp +243 -0
- data/ext/common/Exceptions.h +13 -0
- data/ext/common/FileChangeChecker.h +209 -0
- data/ext/common/Logging.h +3 -2
- data/ext/common/MessageChannel.h +10 -10
- data/ext/common/PoolOptions.h +72 -5
- data/ext/common/SpawnManager.h +11 -8
- data/ext/common/StandardApplicationPool.h +38 -39
- data/ext/common/StaticString.h +1 -0
- data/ext/common/StringListCreator.h +83 -0
- data/ext/common/SystemTime.h +3 -2
- data/ext/common/Timer.h +88 -0
- data/ext/common/Utils.cpp +161 -42
- data/ext/common/Utils.h +62 -31
- data/ext/common/Version.h +1 -1
- data/ext/nginx/Configuration.c +0 -4
- data/ext/nginx/ContentHandler.c +8 -6
- data/ext/nginx/HelperServer.cpp +45 -55
- data/ext/nginx/HttpStatusExtractor.h +4 -0
- data/ext/nginx/StaticContentHandler.c +25 -5
- data/ext/nginx/config +3 -0
- data/ext/nginx/ngx_http_passenger_module.c +72 -17
- data/ext/nginx/ngx_http_passenger_module.h +2 -2
- data/lib/phusion_passenger/abstract_request_handler.rb +15 -7
- data/lib/phusion_passenger/abstract_server.rb +16 -2
- data/lib/phusion_passenger/admin_tools/control_process.rb +36 -25
- data/lib/phusion_passenger/constants.rb +1 -1
- data/lib/phusion_passenger/dependencies.rb +10 -0
- data/lib/phusion_passenger/platform_info.rb +1 -1
- data/lib/phusion_passenger/rack/application_spawner.rb +21 -2
- data/lib/phusion_passenger/rack/request_handler.rb +10 -0
- data/lib/phusion_passenger/railz/application_spawner.rb +38 -2
- data/lib/phusion_passenger/railz/framework_spawner.rb +26 -28
- data/lib/phusion_passenger/railz/request_handler.rb +5 -1
- data/lib/phusion_passenger/spawn_manager.rb +6 -2
- data/lib/phusion_passenger/utils.rb +79 -27
- data/misc/rake/cplusplus.rb +5 -5
- data/test/ApplicationPoolServerTest.cpp +42 -0
- data/test/ApplicationPoolTest.cpp +255 -267
- data/test/Base64Test.cpp +48 -0
- data/test/CachedFileStatTest.cpp +243 -103
- data/test/FileChangeCheckerTest.cpp +331 -0
- data/test/PoolOptionsTest.cpp +80 -0
- data/test/UtilsTest.cpp +5 -17
- data/test/integration_tests/apache2_tests.rb +15 -4
- data/test/integration_tests/mycook_spec.rb +3 -4
- data/test/oxt/syscall_interruption_test.cpp +2 -14
- data/test/ruby/abstract_server_collection_spec.rb +1 -1
- data/test/ruby/abstract_server_spec.rb +35 -1
- data/test/ruby/rack/application_spawner_spec.rb +23 -6
- data/test/ruby/rails/application_spawner_spec.rb +6 -6
- data/test/ruby/rails/framework_spawner_spec.rb +6 -5
- data/test/ruby/rails/minimal_spawner_spec.rb +19 -0
- data/test/ruby/rails/spawner_error_handling_spec.rb +62 -7
- data/test/ruby/spawn_manager_spec.rb +10 -7
- data/test/ruby/spawn_server_spec.rb +1 -1
- data/test/ruby/utils_spec.rb +193 -20
- data/test/ruby/wsgi/application_spawner_spec.rb +3 -1
- data/test/stub/apache2/httpd.conf.erb +3 -0
- data/test/stub/rack/config.ru +1 -1
- data/test/stub/rails_apps/mycook/app/controllers/welcome_controller.rb +8 -0
- data/test/support/Support.cpp +84 -0
- data/test/support/Support.h +66 -8
- data/test/support/config.rb +14 -2
- data/test/support/test_helper.rb +5 -0
- data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +123 -116
- data/vendor/rack-1.0.0-git/lib/rack/cascade.rb +17 -12
- data/vendor/rack-1.0.0-git/lib/rack/commonlogger.rb +34 -43
- data/vendor/rack-1.0.0-git/lib/rack/handler/cgi.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/handler/fastcgi.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/handler/lsws.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/handler/mongrel.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/handler/scgi.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/handler/webrick.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/mock.rb +4 -17
- data/vendor/rack-1.0.0-git/lib/rack/request.rb +3 -9
- data/vendor/rack-1.0.0-git/lib/rack/rewindable_input.rb +2 -0
- data/vendor/rack-1.0.0-git/lib/rack/utils.rb +38 -12
- metadata +231 -186
- data/ext/common/FileChecker.h +0 -112
- data/test/FileCheckerTest.cpp +0 -79
- data/test/stub/minimal-railsapp/README +0 -3
- data/test/stub/minimal-railsapp/config/application.rb +0 -0
- data/test/stub/minimal-railsapp/config/environment.rb +0 -3
- data/test/stub/minimal-railsapp/vendor/rails/actionmailer/lib/action_mailer.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_controller.rb +0 -10
- data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_pack.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_view.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/activerecord/lib/active_record.rb +0 -7
- data/test/stub/minimal-railsapp/vendor/rails/activeresource/lib/active_resource.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support.rb +0 -17
- data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support/whiny_nil.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/railties/lib/dispatcher.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/railties/lib/initializer.rb +0 -8
- data/test/stub/minimal-railsapp/vendor/rails/railties/lib/ruby_version_check.rb +0 -1
- data/test/stub/railsapp/app/controllers/application.rb +0 -12
- data/test/stub/railsapp/app/controllers/bar_controller.rb +0 -5
- data/test/stub/railsapp/app/controllers/bar_controller_1.txt +0 -5
- data/test/stub/railsapp/app/controllers/bar_controller_2.txt +0 -5
- data/test/stub/railsapp/app/controllers/foo_controller.rb +0 -9
- data/test/stub/railsapp/app/helpers/application_helper.rb +0 -3
- data/test/stub/railsapp/config/boot.rb +0 -108
- data/test/stub/railsapp/config/database.yml +0 -19
- data/test/stub/railsapp/config/environment.rb +0 -59
- data/test/stub/railsapp/config/environments/development.rb +0 -18
- data/test/stub/railsapp/config/environments/production.rb +0 -19
- data/test/stub/railsapp/config/initializers/inflections.rb +0 -10
- data/test/stub/railsapp/config/initializers/mime_types.rb +0 -5
- data/test/stub/railsapp/config/routes.rb +0 -35
- data/test/stub/railsapp/public/useless.txt +0 -1
- data/test/stub/railsapp2/app/controllers/application.rb +0 -12
- data/test/stub/railsapp2/app/controllers/foo_controller.rb +0 -5
- data/test/stub/railsapp2/app/helpers/application_helper.rb +0 -3
- data/test/stub/railsapp2/config/boot.rb +0 -108
- data/test/stub/railsapp2/config/database.yml +0 -19
- data/test/stub/railsapp2/config/environment.rb +0 -59
- data/test/stub/railsapp2/config/environments/development.rb +0 -18
- data/test/stub/railsapp2/config/environments/production.rb +0 -19
- data/test/stub/railsapp2/config/initializers/inflections.rb +0 -10
- data/test/stub/railsapp2/config/initializers/mime_types.rb +0 -5
- data/test/stub/railsapp2/config/routes.rb +0 -35
- data/test/stub/railsapp2/public/useless.txt +0 -1
data/ext/boost/mpl/apply.hpp
CHANGED
@@ -135,7 +135,10 @@ struct apply
|
|
135
135
|
|
136
136
|
///// iteration, depth == 1
|
137
137
|
|
138
|
-
|
138
|
+
// For gcc 4.4 compatability, we must include the
|
139
|
+
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
140
|
+
#else // BOOST_PP_IS_ITERATING
|
141
|
+
#if BOOST_PP_ITERATION_DEPTH() == 1
|
139
142
|
|
140
143
|
# define i_ BOOST_PP_FRAME_ITERATION(1)
|
141
144
|
|
@@ -222,4 +225,5 @@ struct apply_chooser<i_>
|
|
222
225
|
|
223
226
|
# undef i_
|
224
227
|
|
228
|
+
#endif // BOOST_PP_ITERATION_DEPTH()
|
225
229
|
#endif // BOOST_PP_IS_ITERATING
|
@@ -78,7 +78,10 @@ namespace boost { namespace mpl {
|
|
78
78
|
|
79
79
|
///// iteration, depth == 1
|
80
80
|
|
81
|
-
|
81
|
+
// For gcc 4.4 compatability, we must include the
|
82
|
+
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
83
|
+
#else
|
84
|
+
#if BOOST_PP_ITERATION_DEPTH() == 1
|
82
85
|
|
83
86
|
# define i_ BOOST_PP_FRAME_ITERATION(1)
|
84
87
|
|
@@ -196,5 +199,5 @@ struct BOOST_PP_CAT(apply_wrap_impl,i_)<
|
|
196
199
|
};
|
197
200
|
|
198
201
|
# undef j_
|
199
|
-
|
202
|
+
#endif // BOOST_PP_ITERATION_DEPTH()
|
200
203
|
#endif // BOOST_PP_IS_ITERATING
|
@@ -227,7 +227,10 @@ BOOST_MPL_AUX_NA_SPEC2(2, 3, lambda)
|
|
227
227
|
|
228
228
|
///// iteration, depth == 1
|
229
229
|
|
230
|
-
|
230
|
+
// For gcc 4.4 compatability, we must include the
|
231
|
+
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
232
|
+
#else // BOOST_PP_IS_ITERATING
|
233
|
+
#if BOOST_PP_ITERATION_DEPTH() == 1
|
231
234
|
#define i_ BOOST_PP_FRAME_ITERATION(1)
|
232
235
|
|
233
236
|
#if i_ > 0
|
@@ -347,4 +350,5 @@ struct lambda<
|
|
347
350
|
};
|
348
351
|
|
349
352
|
#undef i_
|
353
|
+
#endif // BOOST_PP_ITERATION_DEPTH()
|
350
354
|
#endif // BOOST_PP_IS_ITERATING
|
data/ext/boost/mpl/bind.hpp
CHANGED
@@ -361,7 +361,10 @@ BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(
|
|
361
361
|
|
362
362
|
///// iteration, depth == 1
|
363
363
|
|
364
|
-
|
364
|
+
// For gcc 4.4 compatability, we must include the
|
365
|
+
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
366
|
+
#else // BOOST_PP_IS_ITERATING
|
367
|
+
#if BOOST_PP_ITERATION_DEPTH() == 1
|
365
368
|
|
366
369
|
# define i_ BOOST_PP_FRAME_ITERATION(1)
|
367
370
|
|
@@ -544,4 +547,5 @@ struct bind_chooser<i_>
|
|
544
547
|
# endif
|
545
548
|
# undef j_
|
546
549
|
|
550
|
+
#endif // BOOST_PP_ITERATION_DEPTH()
|
547
551
|
#endif // BOOST_PP_IS_ITERATING
|
data/ext/common/Application.h
CHANGED
@@ -283,7 +283,7 @@ private:
|
|
283
283
|
if (fd != -1) {
|
284
284
|
int ret = syscalls::shutdown(fd, SHUT_RD);
|
285
285
|
if (ret == -1) {
|
286
|
-
throw SystemException("Cannot shutdown the
|
286
|
+
throw SystemException("Cannot shutdown the reader stream",
|
287
287
|
errno);
|
288
288
|
}
|
289
289
|
}
|
@@ -304,11 +304,16 @@ private:
|
|
304
304
|
TRACE_POINT();
|
305
305
|
if (fd != -1) {
|
306
306
|
int ret = syscalls::close(fd);
|
307
|
+
fd = -1;
|
307
308
|
if (ret == -1) {
|
308
|
-
|
309
|
-
|
309
|
+
if (errno == EIO) {
|
310
|
+
throw SystemException("A write operation on the session stream failed",
|
311
|
+
errno);
|
312
|
+
} else {
|
313
|
+
throw SystemException("Cannot close the session stream",
|
314
|
+
errno);
|
315
|
+
}
|
310
316
|
}
|
311
|
-
fd = -1;
|
312
317
|
}
|
313
318
|
}
|
314
319
|
|
@@ -329,33 +334,7 @@ private:
|
|
329
334
|
|
330
335
|
SessionPtr connectToUnixServer(const function<void()> &closeCallback) const {
|
331
336
|
TRACE_POINT();
|
332
|
-
int fd
|
333
|
-
|
334
|
-
do {
|
335
|
-
fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
336
|
-
} while (fd == -1 && errno == EINTR);
|
337
|
-
if (fd == -1) {
|
338
|
-
throw SystemException("Cannot create a new unconnected Unix socket", errno);
|
339
|
-
}
|
340
|
-
|
341
|
-
struct sockaddr_un addr;
|
342
|
-
addr.sun_family = AF_UNIX;
|
343
|
-
strncpy(addr.sun_path, listenSocketName.c_str(), sizeof(addr.sun_path));
|
344
|
-
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
345
|
-
do {
|
346
|
-
ret = ::connect(fd, (const sockaddr *) &addr, sizeof(addr));
|
347
|
-
} while (ret == -1 && errno == EINTR);
|
348
|
-
if (ret == -1) {
|
349
|
-
int e = errno;
|
350
|
-
string message("Cannot connect to Unix socket '");
|
351
|
-
message.append(listenSocketName);
|
352
|
-
message.append("'");
|
353
|
-
do {
|
354
|
-
ret = close(fd);
|
355
|
-
} while (ret == -1 && errno == EINTR);
|
356
|
-
throw SystemException(message, e);
|
357
|
-
}
|
358
|
-
|
337
|
+
int fd = Passenger::connectToUnixServer(listenSocketName.c_str());
|
359
338
|
return ptr(new StandardSession(pid, closeCallback, fd));
|
360
339
|
}
|
361
340
|
|
@@ -510,6 +489,7 @@ public:
|
|
510
489
|
* @post this->getSessions() == old->getSessions() + 1
|
511
490
|
* @throws SystemException Something went wrong during the connection process.
|
512
491
|
* @throws IOException Something went wrong during the connection process.
|
492
|
+
* @throws boost::thread_interrupted
|
513
493
|
*/
|
514
494
|
SessionPtr connect(const function<void()> &closeCallback) const {
|
515
495
|
TRACE_POINT();
|
@@ -126,7 +126,8 @@ public:
|
|
126
126
|
* @throw BusyException The application pool is too busy right now, and cannot
|
127
127
|
* satisfy the request. One should either abort, or try again later.
|
128
128
|
* @throw IOException Something else went wrong.
|
129
|
-
* @throw thread_interrupted
|
129
|
+
* @throw boost::thread_interrupted
|
130
|
+
* @throws Anything thrown by options.environmentVariables->getItems().
|
130
131
|
* @note Applications are uniquely identified with the application root
|
131
132
|
* string. So although <tt>appRoot</tt> does not have to be absolute, it
|
132
133
|
* should be. If one calls <tt>get("/home/foo")</tt> and
|
@@ -216,7 +216,7 @@ private:
|
|
216
216
|
if (fd != -1) {
|
217
217
|
int ret = syscalls::shutdown(fd, SHUT_RD);
|
218
218
|
if (ret == -1) {
|
219
|
-
throw SystemException("Cannot shutdown the
|
219
|
+
throw SystemException("Cannot shutdown the reader stream",
|
220
220
|
errno);
|
221
221
|
}
|
222
222
|
}
|
@@ -235,11 +235,16 @@ private:
|
|
235
235
|
virtual void closeStream() {
|
236
236
|
if (fd != -1) {
|
237
237
|
int ret = syscalls::close(fd);
|
238
|
+
fd = -1;
|
238
239
|
if (ret == -1) {
|
239
|
-
|
240
|
-
|
240
|
+
if (errno == EIO) {
|
241
|
+
throw SystemException("A write operation on the session stream failed",
|
242
|
+
errno);
|
243
|
+
} else {
|
244
|
+
throw SystemException("Cannot close the session stream",
|
245
|
+
errno);
|
246
|
+
}
|
241
247
|
}
|
242
|
-
fd = -1;
|
243
248
|
}
|
244
249
|
}
|
245
250
|
|
@@ -380,12 +385,18 @@ private:
|
|
380
385
|
vector<string> args;
|
381
386
|
int stream;
|
382
387
|
bool result;
|
388
|
+
bool serverMightNeedEnvironmentVariables = true;
|
383
389
|
|
390
|
+
/* Send a 'get' request to the ApplicationPool server.
|
391
|
+
* For efficiency reasons, we do not send the data for
|
392
|
+
* options.environmentVariables over the wire yet until
|
393
|
+
* it's necessary.
|
394
|
+
*/
|
384
395
|
try {
|
385
396
|
vector<string> args;
|
386
397
|
|
387
398
|
args.push_back("get");
|
388
|
-
options.toVector(args);
|
399
|
+
options.toVector(args, false);
|
389
400
|
channel.write(args);
|
390
401
|
} catch (const SystemException &e) {
|
391
402
|
UPDATE_TRACE_POINT();
|
@@ -395,22 +406,52 @@ private:
|
|
395
406
|
message.append(e.brief());
|
396
407
|
throw SystemException(message, e.code());
|
397
408
|
}
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
409
|
+
|
410
|
+
/* The first few replies from the server might be for requesting
|
411
|
+
* environment variables in the pool options object, so keep handling
|
412
|
+
* these requests until we receive a different reply.
|
413
|
+
*/
|
414
|
+
while (serverMightNeedEnvironmentVariables) {
|
415
|
+
try {
|
416
|
+
result = channel.read(args);
|
417
|
+
} catch (const SystemException &e) {
|
418
|
+
UPDATE_TRACE_POINT();
|
419
|
+
data->disconnect();
|
420
|
+
throw SystemException("Could not read a response from "
|
421
|
+
"the ApplicationPool server for the 'get' command", e.code());
|
422
|
+
}
|
423
|
+
if (!result) {
|
424
|
+
UPDATE_TRACE_POINT();
|
425
|
+
data->disconnect();
|
426
|
+
throw IOException("The ApplicationPool server unexpectedly "
|
427
|
+
"closed the connection while we're reading a response "
|
428
|
+
"for the 'get' command.");
|
429
|
+
}
|
430
|
+
|
431
|
+
if (args[0] == "getEnvironmentVariables") {
|
432
|
+
try {
|
433
|
+
if (options.environmentVariables) {
|
434
|
+
UPDATE_TRACE_POINT();
|
435
|
+
channel.writeScalar(options.serializeEnvironmentVariables());
|
436
|
+
} else {
|
437
|
+
UPDATE_TRACE_POINT();
|
438
|
+
channel.writeScalar("");
|
439
|
+
}
|
440
|
+
} catch (const SystemException &e) {
|
441
|
+
data->disconnect();
|
442
|
+
throw SystemException("Could not send a response "
|
443
|
+
"for the 'getEnvironmentVariables' request "
|
444
|
+
"to the ApplicationPool server",
|
445
|
+
e.code());
|
446
|
+
}
|
447
|
+
} else {
|
448
|
+
serverMightNeedEnvironmentVariables = false;
|
449
|
+
}
|
413
450
|
}
|
451
|
+
|
452
|
+
/* We've now received a reply other than "getEnvironmentVariables".
|
453
|
+
* Handle this...
|
454
|
+
*/
|
414
455
|
if (args[0] == "ok") {
|
415
456
|
UPDATE_TRACE_POINT();
|
416
457
|
pid_t pid = (pid_t) atol(args[1]);
|
@@ -288,6 +288,131 @@ private:
|
|
288
288
|
/** Last used session ID. */
|
289
289
|
int lastSessionID;
|
290
290
|
|
291
|
+
class ClientCommunicationError: public oxt::tracable_exception {
|
292
|
+
private:
|
293
|
+
string briefMessage;
|
294
|
+
string systemMessage;
|
295
|
+
string fullMessage;
|
296
|
+
int m_code;
|
297
|
+
public:
|
298
|
+
/**
|
299
|
+
* Create a new ClientCommunicationError.
|
300
|
+
*
|
301
|
+
* @param briefMessage A brief message describing the error.
|
302
|
+
* @param errorCode An optional error code, i.e. the value of errno right after the error occured, if applicable.
|
303
|
+
* @note A system description of the error will be appended to the given message.
|
304
|
+
* For example, if <tt>errorCode</tt> is <tt>EBADF</tt>, and <tt>briefMessage</tt>
|
305
|
+
* is <em>"Something happened"</em>, then what() will return <em>"Something happened: Bad
|
306
|
+
* file descriptor (10)"</em> (if 10 is the number for EBADF).
|
307
|
+
* @post code() == errorCode
|
308
|
+
* @post brief() == briefMessage
|
309
|
+
*/
|
310
|
+
ClientCommunicationError(const string &briefMessage, int errorCode = -1) {
|
311
|
+
if (errorCode != -1) {
|
312
|
+
stringstream str;
|
313
|
+
|
314
|
+
str << strerror(errorCode) << " (" << errorCode << ")";
|
315
|
+
systemMessage = str.str();
|
316
|
+
}
|
317
|
+
setBriefMessage(briefMessage);
|
318
|
+
m_code = errorCode;
|
319
|
+
}
|
320
|
+
|
321
|
+
virtual ~ClientCommunicationError() throw() {}
|
322
|
+
|
323
|
+
virtual const char *what() const throw() {
|
324
|
+
return fullMessage.c_str();
|
325
|
+
}
|
326
|
+
|
327
|
+
void setBriefMessage(const string &message) {
|
328
|
+
briefMessage = message;
|
329
|
+
if (systemMessage.empty()) {
|
330
|
+
fullMessage = briefMessage;
|
331
|
+
} else {
|
332
|
+
fullMessage = briefMessage + ": " + systemMessage;
|
333
|
+
}
|
334
|
+
}
|
335
|
+
|
336
|
+
/**
|
337
|
+
* The value of <tt>errno</tt> at the time the error occured.
|
338
|
+
*/
|
339
|
+
int code() const throw() {
|
340
|
+
return m_code;
|
341
|
+
}
|
342
|
+
|
343
|
+
/**
|
344
|
+
* Returns a brief version of the exception message. This message does
|
345
|
+
* not include the system error description, and is equivalent to the
|
346
|
+
* value of the <tt>message</tt> parameter as passed to the constructor.
|
347
|
+
*/
|
348
|
+
string brief() const throw() {
|
349
|
+
return briefMessage;
|
350
|
+
}
|
351
|
+
|
352
|
+
/**
|
353
|
+
* Returns the system's error message. This message contains both the
|
354
|
+
* content of <tt>strerror(errno)</tt> and the errno number itself.
|
355
|
+
*
|
356
|
+
* @post if code() == -1: result.empty()
|
357
|
+
*/
|
358
|
+
string sys() const throw() {
|
359
|
+
return systemMessage;
|
360
|
+
}
|
361
|
+
};
|
362
|
+
|
363
|
+
/**
|
364
|
+
* A StringListCreator which fetches its items from the client.
|
365
|
+
* Used as an optimization for ApplicationPoolServer::Client.get():
|
366
|
+
* environment variables are only serialized by the client process
|
367
|
+
* if a new backend process is being spawned.
|
368
|
+
*/
|
369
|
+
class EnvironmentVariablesFetcher: public StringListCreator {
|
370
|
+
private:
|
371
|
+
MessageChannel &channel;
|
372
|
+
PoolOptions &options;
|
373
|
+
public:
|
374
|
+
EnvironmentVariablesFetcher(MessageChannel &theChannel, PoolOptions &theOptions)
|
375
|
+
: channel(theChannel),
|
376
|
+
options(theOptions)
|
377
|
+
{ }
|
378
|
+
|
379
|
+
/**
|
380
|
+
* @throws ClientCommunicationError
|
381
|
+
*/
|
382
|
+
virtual const StringListPtr getItems() const {
|
383
|
+
string data;
|
384
|
+
|
385
|
+
/* If an I/O error occurred while communicating with the client,
|
386
|
+
* then throw a ClientCommunicationException, which will bubble
|
387
|
+
* all the way up to the thread main loop, where the connection
|
388
|
+
* with the client will be broken.
|
389
|
+
*/
|
390
|
+
try {
|
391
|
+
channel.write("getEnvironmentVariables", NULL);
|
392
|
+
} catch (const SystemException &e) {
|
393
|
+
throw ClientCommunicationError(
|
394
|
+
"Unable to send a 'getEnvironmentVariables' request to the client",
|
395
|
+
e.code());
|
396
|
+
}
|
397
|
+
try {
|
398
|
+
if (!channel.readScalar(data)) {
|
399
|
+
throw ClientCommunicationError("Unable to read a reply from the client for the 'getEnvironmentVariables' request.");
|
400
|
+
}
|
401
|
+
} catch (const SystemException &e) {
|
402
|
+
throw ClientCommunicationError(
|
403
|
+
"Unable to read a reply from the client for the 'getEnvironmentVariables' request",
|
404
|
+
e.code());
|
405
|
+
}
|
406
|
+
|
407
|
+
if (!data.empty()) {
|
408
|
+
SimpleStringListCreator list(data);
|
409
|
+
return list.getItems();
|
410
|
+
} else {
|
411
|
+
return ptr(new StringList());
|
412
|
+
}
|
413
|
+
}
|
414
|
+
};
|
415
|
+
|
291
416
|
void processGet(const vector<string> &args) {
|
292
417
|
TRACE_POINT();
|
293
418
|
Application::SessionPtr session;
|
@@ -295,6 +420,7 @@ private:
|
|
295
420
|
|
296
421
|
try {
|
297
422
|
PoolOptions options(args, 1);
|
423
|
+
options.environmentVariables = ptr(new EnvironmentVariablesFetcher(channel, options));
|
298
424
|
session = server.pool->get(options);
|
299
425
|
sessions[lastSessionID] = session;
|
300
426
|
lastSessionID++;
|
@@ -331,12 +457,14 @@ private:
|
|
331
457
|
UPDATE_TRACE_POINT();
|
332
458
|
channel.write("ok", toString(session->getPid()).c_str(),
|
333
459
|
toString(lastSessionID - 1).c_str(), NULL);
|
460
|
+
UPDATE_TRACE_POINT();
|
334
461
|
channel.writeFileDescriptor(session->getStream());
|
335
|
-
session->closeStream();
|
336
|
-
} catch (const exception &) {
|
337
462
|
UPDATE_TRACE_POINT();
|
338
|
-
|
339
|
-
|
463
|
+
session->closeStream();
|
464
|
+
} catch (const exception &e) {
|
465
|
+
P_TRACE(3, "Client " << this << ": could not send "
|
466
|
+
"'ok' back to the ApplicationPool client: " <<
|
467
|
+
e.what());
|
340
468
|
sessions.erase(lastSessionID - 1);
|
341
469
|
throw;
|
342
470
|
}
|
@@ -33,6 +33,8 @@
|
|
33
33
|
|
34
34
|
#include <string>
|
35
35
|
#include <sys/types.h>
|
36
|
+
#include <sys/socket.h>
|
37
|
+
#include <sys/un.h>
|
36
38
|
#include <sys/stat.h>
|
37
39
|
#include <cstdio>
|
38
40
|
#include <unistd.h>
|
@@ -40,6 +42,7 @@
|
|
40
42
|
|
41
43
|
#include "StandardApplicationPool.h"
|
42
44
|
#include "MessageChannel.h"
|
45
|
+
#include "Exceptions.h"
|
43
46
|
#include "Logging.h"
|
44
47
|
#include "Utils.h"
|
45
48
|
|
@@ -51,72 +54,176 @@ using namespace std;
|
|
51
54
|
|
52
55
|
/**
|
53
56
|
* An ApplicationPoolStatusReporter allows commandline admin tools to inspect
|
54
|
-
* the status of a StandardApplicationPool. It does so by creating a
|
55
|
-
* in the Passenger temp folder
|
57
|
+
* the status of a StandardApplicationPool. It does so by creating a Unix socket
|
58
|
+
* in the Passenger temp folder, which tools can connect to to query for
|
59
|
+
* information.
|
56
60
|
*
|
57
|
-
* An ApplicationPoolStatusReporter creates a background thread
|
58
|
-
*
|
59
|
-
*
|
60
|
-
* object.
|
61
|
+
* An ApplicationPoolStatusReporter creates a background thread for handling
|
62
|
+
* connections on the socket. This thread will be automatically cleaned up upon
|
63
|
+
* destroying the ApplicationPoolStatusReporter object.
|
61
64
|
*/
|
62
65
|
class ApplicationPoolStatusReporter {
|
63
66
|
private:
|
67
|
+
/**
|
68
|
+
* Wrapper class around a file descriptor integer, for RAII behavior.
|
69
|
+
*
|
70
|
+
* A FileDescriptor object behaves just like an int, so that you can pass it to
|
71
|
+
* system calls such as read(). It performs reference counting. When the last
|
72
|
+
* copy of a FileDescriptor has been destroyed, the underlying file descriptor
|
73
|
+
* will be automatically closed.
|
74
|
+
*/
|
75
|
+
class FileDescriptor {
|
76
|
+
private:
|
77
|
+
struct SharedData {
|
78
|
+
int fd;
|
79
|
+
|
80
|
+
/**
|
81
|
+
* Constructor to assign this file descriptor's handle.
|
82
|
+
*/
|
83
|
+
SharedData(int fd) {
|
84
|
+
this->fd = fd;
|
85
|
+
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Attempts to close this file descriptor. When created on the stack,
|
89
|
+
* this destructor will automatically be invoked as a result of C++
|
90
|
+
* semantics when exiting the scope this object was created in. This
|
91
|
+
* ensures that stack created objects with destructors like these will
|
92
|
+
* de-allocate their resources upon leaving their corresponding scope.
|
93
|
+
* This pattern is also known Resource Acquisition Is Initialization (RAII).
|
94
|
+
*
|
95
|
+
* @throws SystemException File descriptor could not be closed.
|
96
|
+
*/
|
97
|
+
~SharedData() {
|
98
|
+
this_thread::disable_syscall_interruption dsi;
|
99
|
+
if (syscalls::close(fd) == -1) {
|
100
|
+
throw SystemException("Cannot close file descriptor", errno);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
};
|
104
|
+
|
105
|
+
/* Shared pointer for reference counting on this file descriptor */
|
106
|
+
shared_ptr<SharedData> data;
|
107
|
+
|
108
|
+
public:
|
109
|
+
FileDescriptor() {
|
110
|
+
// Do nothing.
|
111
|
+
}
|
112
|
+
|
113
|
+
/**
|
114
|
+
* Creates a new FileDescriptor instance with the given fd as a handle.
|
115
|
+
*/
|
116
|
+
FileDescriptor(int fd) {
|
117
|
+
data = ptr(new SharedData(fd));
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Overloads the integer cast operator so that it will return the file
|
122
|
+
* descriptor handle as an integer.
|
123
|
+
*
|
124
|
+
* @return This file descriptor's handle as an integer.
|
125
|
+
*/
|
126
|
+
operator int () const {
|
127
|
+
return data->fd;
|
128
|
+
}
|
129
|
+
};
|
130
|
+
|
64
131
|
/** The application pool to monitor. */
|
65
132
|
StandardApplicationPoolPtr pool;
|
66
133
|
|
67
|
-
/** The
|
134
|
+
/** The socket's filename. */
|
68
135
|
char filename[PATH_MAX];
|
69
136
|
|
70
|
-
/** The
|
71
|
-
|
137
|
+
/** The socket's file descriptor. */
|
138
|
+
int serverFd;
|
139
|
+
|
140
|
+
/** The main thread. */
|
141
|
+
oxt::thread *mainThread;
|
72
142
|
|
73
|
-
|
143
|
+
/** The mutex which protects the 'threads' member. */
|
144
|
+
boost::mutex threadsLock;
|
145
|
+
|
146
|
+
/** A map which maps a client file descriptor to its handling thread. */
|
147
|
+
map< int, shared_ptr<oxt::thread> > threads;
|
148
|
+
|
149
|
+
void writeScalarAndIgnoreErrors(MessageChannel &channel, const string &data) {
|
150
|
+
try {
|
151
|
+
channel.writeScalar(data);
|
152
|
+
} catch (const SystemException &e) {
|
153
|
+
// Don't care about write errors.
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
void mainThreadFunction() {
|
74
158
|
TRACE_POINT();
|
75
159
|
try {
|
76
160
|
while (!this_thread::interruption_requested()) {
|
77
|
-
struct stat buf;
|
78
|
-
int ret;
|
79
|
-
|
80
161
|
UPDATE_TRACE_POINT();
|
81
|
-
|
82
|
-
|
83
|
-
} while (ret == -1 && errno == EINTR);
|
84
|
-
if (ret == -1 || !S_ISFIFO(buf.st_mode)) {
|
85
|
-
// Something bad happened with the status
|
86
|
-
// report FIFO, so we bail out.
|
87
|
-
break;
|
88
|
-
}
|
162
|
+
sockaddr_un addr;
|
163
|
+
socklen_t addr_len = sizeof(addr);
|
89
164
|
|
90
|
-
|
91
|
-
|
92
|
-
if (f == NULL) {
|
165
|
+
FileDescriptor fd(syscalls::accept(serverFd, (struct sockaddr *) &addr, &addr_len));
|
166
|
+
if (fd == -1) {
|
93
167
|
int e = errno;
|
94
|
-
P_ERROR("Cannot
|
95
|
-
filename << ": " <<
|
168
|
+
P_ERROR("Cannot accept new client on status reporter socket: " <<
|
96
169
|
strerror(e) << " (" << e << ")");
|
97
170
|
break;
|
98
171
|
}
|
99
172
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
173
|
+
boost::lock_guard<boost::mutex> l(threadsLock);
|
174
|
+
this_thread::disable_syscall_interruption dsi;
|
175
|
+
this_thread::disable_interruption di;
|
176
|
+
shared_ptr<oxt::thread> thread(new oxt::thread(
|
177
|
+
bind(&ApplicationPoolStatusReporter::clientThreadFunction, this, fd),
|
178
|
+
"Status reporter client thread " + toString(fd),
|
179
|
+
1024 * 128
|
180
|
+
));
|
181
|
+
threads[fd] = thread;
|
182
|
+
}
|
183
|
+
} catch (const boost::thread_interrupted &) {
|
184
|
+
P_TRACE(2, "Status reporter main thread interrupted.");
|
185
|
+
} catch (const exception &e) {
|
186
|
+
P_ERROR("Error in status reporter main thread: " << e.what());
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
void clientThreadFunction(FileDescriptor fd) {
|
191
|
+
TRACE_POINT();
|
192
|
+
MessageChannel channel(fd);
|
193
|
+
|
194
|
+
try {
|
195
|
+
while (!this_thread::interruption_requested()) {
|
196
|
+
vector<string> args;
|
107
197
|
|
108
198
|
UPDATE_TRACE_POINT();
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
199
|
+
if (!channel.read(args) || args.size() < 1) {
|
200
|
+
break;
|
201
|
+
}
|
202
|
+
|
203
|
+
if (args[0] == "backtraces") {
|
204
|
+
UPDATE_TRACE_POINT();
|
205
|
+
writeScalarAndIgnoreErrors(channel, oxt::thread::all_backtraces());
|
206
|
+
} else if (args[0] == "status") {
|
207
|
+
UPDATE_TRACE_POINT();
|
208
|
+
writeScalarAndIgnoreErrors(channel, pool->toString());
|
209
|
+
} else if (args[0] == "status_xml") {
|
210
|
+
UPDATE_TRACE_POINT();
|
211
|
+
writeScalarAndIgnoreErrors(channel, pool->toXml());
|
212
|
+
} else {
|
213
|
+
P_ERROR("Error in status reporter client thread: unknown query '" <<
|
214
|
+
args[0] << "'.");
|
114
215
|
}
|
115
|
-
syscalls::fclose(f);
|
116
216
|
}
|
117
217
|
} catch (const boost::thread_interrupted &) {
|
118
|
-
P_TRACE(2, "Status
|
218
|
+
P_TRACE(2, "Status reporter client thread " << fd << " interrupted.");
|
219
|
+
} catch (const exception &e) {
|
220
|
+
P_ERROR("Error in status reporter client thread: " << e.what());
|
119
221
|
}
|
222
|
+
|
223
|
+
boost::lock_guard<boost::mutex> l(threadsLock);
|
224
|
+
this_thread::disable_syscall_interruption dsi;
|
225
|
+
this_thread::disable_interruption di;
|
226
|
+
threads.erase(fd);
|
120
227
|
}
|
121
228
|
|
122
229
|
public:
|
@@ -134,9 +241,11 @@ public:
|
|
134
241
|
* -1 if the current user should be set as owner.
|
135
242
|
* @param gid The GID of the user who should own the FIFO file, or
|
136
243
|
* -1 if the current group should be set as group.
|
137
|
-
* @throws
|
244
|
+
* @throws RuntimeException An error occurred.
|
245
|
+
* @throws SystemException An error occurred while creating the server socket.
|
138
246
|
* @throws boost::thread_resource_error Something went wrong during
|
139
247
|
* creation of the thread.
|
248
|
+
* @throws boost::thread_interrupted A system call has been interrupted.
|
140
249
|
*/
|
141
250
|
ApplicationPoolStatusReporter(StandardApplicationPoolPtr &pool,
|
142
251
|
bool userSwitching,
|
@@ -149,27 +258,17 @@ public:
|
|
149
258
|
createPassengerTempDir(getSystemTempDir(), userSwitching,
|
150
259
|
"nobody", geteuid(), getegid());
|
151
260
|
|
152
|
-
snprintf(filename, sizeof(filename) - 1, "%s/info/status.
|
261
|
+
snprintf(filename, sizeof(filename) - 1, "%s/info/status.socket",
|
153
262
|
getPassengerTempDir().c_str());
|
154
263
|
filename[PATH_MAX - 1] = '\0';
|
264
|
+
serverFd = createUnixServer(filename, 10);
|
155
265
|
|
156
|
-
|
157
|
-
ret = mkfifo(filename, permissions);
|
158
|
-
} while (ret == -1 && errno == EINTR);
|
159
|
-
if (ret == -1 && errno != EEXIST) {
|
160
|
-
int e = errno;
|
161
|
-
string message("Cannot create FIFO '");
|
162
|
-
message.append(filename);
|
163
|
-
message.append("'");
|
164
|
-
throw SystemException(message, e);
|
165
|
-
}
|
166
|
-
|
167
|
-
// It seems that the permissions passed to mkfifo()
|
168
|
-
// aren't respected, so here we chmod the file.
|
266
|
+
/* Set the socket file's permissions... */
|
169
267
|
do {
|
170
268
|
ret = chmod(filename, permissions);
|
171
269
|
} while (ret == -1 && errno == EINTR);
|
172
270
|
|
271
|
+
/* ...and ownership. */
|
173
272
|
if (uid != (uid_t) -1 && gid != (gid_t) -1) {
|
174
273
|
do {
|
175
274
|
ret = chown(filename, uid, gid);
|
@@ -179,31 +278,56 @@ public:
|
|
179
278
|
char message[1024];
|
180
279
|
|
181
280
|
snprintf(message, sizeof(message) - 1,
|
182
|
-
"Cannot set the
|
281
|
+
"Cannot set the owner for socket file '%s' to %lld and its group to %lld",
|
183
282
|
filename, (long long) uid, (long long) gid);
|
184
283
|
message[sizeof(message) - 1] = '\0';
|
284
|
+
do {
|
285
|
+
ret = close(serverFd);
|
286
|
+
} while (ret == -1 && errno == EINTR);
|
185
287
|
throw SystemException(message, e);
|
186
288
|
}
|
187
289
|
}
|
188
290
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
291
|
+
try {
|
292
|
+
mainThread = new oxt::thread(
|
293
|
+
bind(&ApplicationPoolStatusReporter::mainThreadFunction, this),
|
294
|
+
"Status reporter main thread",
|
295
|
+
1024 * 128
|
296
|
+
);
|
297
|
+
} catch (...) {
|
298
|
+
do {
|
299
|
+
ret = close(serverFd);
|
300
|
+
} while (ret == -1 && errno == EINTR);
|
301
|
+
throw;
|
302
|
+
}
|
194
303
|
}
|
195
304
|
|
196
305
|
~ApplicationPoolStatusReporter() {
|
197
306
|
this_thread::disable_syscall_interruption dsi;
|
198
307
|
this_thread::disable_interruption di;
|
199
|
-
|
200
|
-
thr->interrupt_and_join();
|
201
|
-
delete thr;
|
202
|
-
|
203
308
|
int ret;
|
309
|
+
|
204
310
|
do {
|
205
311
|
ret = unlink(filename);
|
206
312
|
} while (ret == -1 && errno == EINTR);
|
313
|
+
|
314
|
+
mainThread->interrupt_and_join();
|
315
|
+
delete mainThread;
|
316
|
+
|
317
|
+
do {
|
318
|
+
ret = close(serverFd);
|
319
|
+
} while (ret == -1 && errno == EINTR);
|
320
|
+
|
321
|
+
/* We make a copy of the data structure here to avoid deadlocks. */
|
322
|
+
map< int, shared_ptr<oxt::thread> > threadsCopy;
|
323
|
+
{
|
324
|
+
boost::lock_guard<boost::mutex> l(threadsLock);
|
325
|
+
threadsCopy = threads;
|
326
|
+
}
|
327
|
+
map< int, shared_ptr<oxt::thread> >::iterator it;
|
328
|
+
for (it = threadsCopy.begin(); it != threadsCopy.end(); it++) {
|
329
|
+
it->second->interrupt_and_join();
|
330
|
+
}
|
207
331
|
}
|
208
332
|
};
|
209
333
|
|