passenger 4.0.5 → 4.0.6
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.tar.gz.asc +7 -7
- data/.travis.yml +1 -2
- data/CONTRIBUTING.md +20 -5
- data/CONTRIBUTORS +67 -0
- data/LICENSE +1 -1
- data/NEWS +48 -0
- data/Rakefile +2 -2
- data/bin/passenger-config +18 -0
- data/bin/passenger-install-apache2-module +2 -0
- data/bin/passenger-install-nginx-module +11 -12
- data/bin/passenger-memory-stats +2 -0
- data/bin/passenger-status +152 -69
- data/build/agents.rb +1 -5
- data/build/basics.rb +26 -13
- data/build/cplusplus_support.rb +9 -0
- data/build/debian.rb +129 -0
- data/build/documentation.rb +6 -2
- data/build/integration_tests.rb +13 -2
- data/build/misc.rb +16 -0
- data/build/packaging.rb +67 -51
- data/build/preprocessor.rb +314 -0
- data/build/test_basics.rb +1 -0
- data/{debian → debian.template}/README.Debian +0 -0
- data/{debian → debian.template}/changelog +131 -0
- data/debian.template/compat +1 -0
- data/debian.template/control +71 -0
- data/debian.template/copyright +385 -0
- data/debian.template/libapache2-mod-passenger.install +3 -0
- data/{debian → debian.template}/libapache2-mod-passenger.postinst +0 -0
- data/{debian → debian.template}/libapache2-mod-passenger.prerm +0 -0
- data/debian.template/locations.ini +12 -0
- data/debian.template/passenger.conf +4 -0
- data/{debian → debian.template}/passenger.load +0 -0
- data/debian.template/patches/series +0 -0
- data/debian.template/repack.sh +42 -0
- data/debian.template/ruby-passenger-dev.install +3 -0
- data/debian.template/ruby-passenger-doc.install +2 -0
- data/debian.template/ruby-passenger.docs +4 -0
- data/debian.template/ruby-passenger.install +11 -0
- data/debian.template/ruby-passenger.manpages +4 -0
- data/debian.template/rules.template +35 -0
- data/debian.template/source/format +1 -0
- data/debian.template/watch +3 -0
- data/dev/run_travis.sh +46 -46
- data/doc/Architectural overview.html +2 -2
- data/doc/Packaging.html +27 -18
- data/doc/Packaging.txt.md +27 -18
- data/doc/Security of user switching support.html +2 -2
- data/doc/Users guide Apache.html +881 -95
- data/doc/Users guide Apache.idmap.txt +48 -6
- data/doc/Users guide Apache.txt +13 -1
- data/doc/Users guide Nginx.html +1063 -190
- data/doc/Users guide Nginx.idmap.txt +89 -45
- data/doc/Users guide Nginx.txt +45 -0
- data/doc/Users guide Standalone.html +7 -7
- data/doc/users_guide_snippets/alternative_for_flying_passenger.txt +1 -0
- data/doc/users_guide_snippets/environment_variables.txt +221 -0
- data/doc/users_guide_snippets/installation.txt +66 -17
- data/doc/users_guide_snippets/support_information.txt +3 -3
- data/doc/users_guide_snippets/tips.txt +352 -40
- data/ext/common/Account.h +4 -3
- data/ext/common/AccountsDatabase.h +6 -6
- data/ext/common/AgentsStarter.h +1 -13
- data/ext/common/ApplicationPool2/DirectSpawner.h +4 -4
- data/ext/common/ApplicationPool2/DummySpawner.h +1 -1
- data/ext/common/ApplicationPool2/Group.h +9 -4
- data/ext/common/ApplicationPool2/Implementation.cpp +6 -1
- data/ext/common/ApplicationPool2/Options.h +65 -37
- data/ext/common/ApplicationPool2/Pool.h +91 -41
- data/ext/common/ApplicationPool2/Process.h +6 -6
- data/ext/common/ApplicationPool2/SmartSpawner.h +14 -14
- data/ext/common/ApplicationPool2/Socket.h +1 -1
- data/ext/common/ApplicationPool2/Spawner.h +24 -16
- data/ext/common/ApplicationPool2/SpawnerFactory.h +9 -1
- data/ext/common/ApplicationPool2/SuperGroup.h +1 -1
- data/ext/common/Constants.h +1 -1
- data/ext/common/Logging.cpp +12 -7
- data/ext/common/MessageServer.h +7 -12
- data/ext/common/MultiLibeio.cpp +5 -5
- data/ext/common/ResourceLocator.h +2 -6
- data/ext/common/ServerInstanceDir.h +37 -10
- data/ext/common/UnionStation.h +10 -10
- data/ext/common/Utils.cpp +30 -4
- data/ext/common/Utils.h +7 -0
- data/ext/common/Utils/BlockingQueue.h +2 -2
- data/ext/common/Utils/Lock.h +2 -2
- data/ext/common/Utils/MessagePassing.h +2 -2
- data/ext/common/Utils/Timer.h +4 -4
- data/ext/common/agents/HelperAgent/AgentOptions.h +2 -0
- data/ext/common/agents/HelperAgent/Main.cpp +57 -16
- data/ext/common/agents/HelperAgent/RequestHandler.h +4 -1
- data/ext/common/agents/LoggingAgent/AdminController.h +91 -0
- data/ext/common/agents/LoggingAgent/LoggingServer.h +46 -29
- data/ext/common/agents/LoggingAgent/Main.cpp +43 -16
- data/ext/common/agents/LoggingAgent/RemoteSender.h +7 -7
- data/ext/common/agents/Watchdog/AgentWatcher.cpp +11 -11
- data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +3 -1
- data/ext/common/agents/Watchdog/Main.cpp +62 -0
- data/ext/libeio/config.guess +206 -167
- data/ext/libeio/config.sub +142 -68
- data/ext/libev/config.guess +304 -290
- data/ext/libev/config.sub +198 -77
- data/ext/nginx/config +4 -0
- data/ext/nginx/ngx_http_passenger_module.c +1 -0
- data/ext/oxt/implementation.cpp +4 -4
- data/lib/phusion_passenger.rb +14 -5
- data/lib/phusion_passenger/abstract_installer.rb +41 -0
- data/lib/phusion_passenger/admin_tools/server_instance.rb +48 -39
- data/lib/phusion_passenger/message_client.rb +31 -7
- data/lib/phusion_passenger/native_support.rb +35 -12
- data/lib/phusion_passenger/packaging.rb +16 -2
- data/lib/phusion_passenger/platform_info/binary_compatibility.rb +6 -31
- data/lib/phusion_passenger/platform_info/operating_system.rb +1 -1
- data/lib/phusion_passenger/preloader_shared_helpers.rb +3 -1
- data/lib/phusion_passenger/request_handler.rb +1 -1
- data/lib/phusion_passenger/standalone/command.rb +6 -6
- data/lib/phusion_passenger/standalone/main.rb +23 -8
- data/lib/phusion_passenger/standalone/package_runtime_command.rb +9 -5
- data/lib/phusion_passenger/standalone/runtime_installer.rb +9 -10
- data/lib/phusion_passenger/standalone/start_command.rb +20 -4
- data/resources/templates/installer_common/freebsd9_broken_cxx_runtime.txt.erb +19 -0
- data/resources/templates/installer_common/low_amount_of_memory_warning.txt.erb +22 -0
- data/resources/templates/standalone/config.erb +3 -2
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +4 -4
- data/test/cxx/ApplicationPool2/PoolTest.cpp +1 -1
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +7 -7
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +9 -9
- data/test/cxx/EventedBufferedInputTest.cpp +17 -17
- data/test/cxx/RequestHandlerTest.cpp +5 -5
- data/test/cxx/ServerInstanceDirTest.cpp +3 -1
- data/test/cxx/TestSupport.h +4 -4
- data/test/cxx/UnionStationTest.cpp +3 -1
- data/test/cxx/UtilsTest.cpp +2 -0
- data/test/integration_tests/apache2_tests.rb +2 -2
- data/test/integration_tests/native_packaging_spec.rb +170 -0
- data/test/ruby/spec_helper.rb +0 -1
- data/test/stub/apache2/httpd.conf.erb +1 -1
- data/test/stub/nginx/nginx.conf.erb +1 -0
- data/test/support/apache2_controller.rb +1 -1
- data/test/support/placebo-preloader.rb +1 -1
- data/test/support/test_helper.rb +5 -2
- metadata +32 -26
- metadata.gz.asc +7 -7
- data/debian/compat +0 -1
- data/debian/control +0 -49
- data/debian/copyright +0 -20
- data/debian/libapache2-mod-passenger.install +0 -1
- data/debian/passenger-common.install +0 -4
- data/debian/passenger.conf +0 -4
- data/debian/prerm +0 -2
- data/debian/rules +0 -37
- data/debian/watch +0 -3
- data/dev/googlecode_upload.py +0 -265
- data/ext/common/agents/HelperAgent/BacktracesServer.h +0 -60
- data/resources/templates/nginx/not_available_when_natively_packaged.txt.erb +0 -8
- data/test/stub/rails3.1/app/assets/javascripts/application.js +0 -9
- data/test/stub/rails3.2/app/assets/javascripts/application.js +0 -15
- data/test/stub/rails_apps/2.3/mycook/public/javascripts/application.js +0 -2
- data/test/stub/rails_apps/2.3/mycook/public/javascripts/controls.js +0 -963
- data/test/stub/rails_apps/2.3/mycook/public/javascripts/dragdrop.js +0 -973
- data/test/stub/rails_apps/2.3/mycook/public/javascripts/effects.js +0 -1128
- data/test/stub/rails_apps/2.3/mycook/public/javascripts/prototype.js +0 -4320
data/ext/common/UnionStation.h
CHANGED
@@ -710,7 +710,7 @@ public:
|
|
710
710
|
}
|
711
711
|
|
712
712
|
void checkinConnection(const ConnectionPtr &connection) {
|
713
|
-
lock_guard<boost::mutex> l(syncher);
|
713
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
714
714
|
if (connectionPool.size() < CONNECTION_POOL_MAX_SIZE) {
|
715
715
|
connectionPool.push_back(connection);
|
716
716
|
} else {
|
@@ -786,7 +786,7 @@ public:
|
|
786
786
|
|
787
787
|
vector<string> args;
|
788
788
|
if (!readArrayMessage(connection->fd, args, &timeout)) {
|
789
|
-
lock_guard<boost::mutex> l(syncher);
|
789
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
790
790
|
P_WARN("The logging agent at " << serverAddress <<
|
791
791
|
" closed the connection (no error message given);" <<
|
792
792
|
" will reconnect in " << reconnectTimeout / 1000000 <<
|
@@ -794,7 +794,7 @@ public:
|
|
794
794
|
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
795
795
|
return createNullLogger();
|
796
796
|
} else if (args.size() == 2 && args[0] == "error") {
|
797
|
-
lock_guard<boost::mutex> l(syncher);
|
797
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
798
798
|
P_WARN("The logging agent at " << serverAddress <<
|
799
799
|
" closed the connection (error message: " << args[1] <<
|
800
800
|
"); will reconnect in " << reconnectTimeout / 1000000 <<
|
@@ -802,7 +802,7 @@ public:
|
|
802
802
|
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
803
803
|
return createNullLogger();
|
804
804
|
} else if (args.empty() || args[0] != "ok") {
|
805
|
-
lock_guard<boost::mutex> l(syncher);
|
805
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
806
806
|
P_WARN("The logging agent at " << serverAddress <<
|
807
807
|
" sent an unexpected reply;" <<
|
808
808
|
" will reconnect in " << reconnectTimeout / 1000000 <<
|
@@ -819,7 +819,7 @@ public:
|
|
819
819
|
unionStationKey);
|
820
820
|
|
821
821
|
} catch (const TimeoutException &) {
|
822
|
-
lock_guard<boost::mutex> l(syncher);
|
822
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
823
823
|
P_WARN("Timeout trying to communicate with the logging agent at " << serverAddress << "; " <<
|
824
824
|
"will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
|
825
825
|
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
@@ -832,7 +832,7 @@ public:
|
|
832
832
|
|
833
833
|
guard.clear();
|
834
834
|
gotErrorResponse = connection->disconnect(errorResponse);
|
835
|
-
lock_guard<boost::mutex> l(syncher);
|
835
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
836
836
|
if (gotErrorResponse) {
|
837
837
|
P_WARN("The logging agent at " << serverAddress <<
|
838
838
|
" closed the connection (error message: " << errorResponse <<
|
@@ -891,7 +891,7 @@ public:
|
|
891
891
|
unionStationKey);
|
892
892
|
|
893
893
|
} catch (const TimeoutException &) {
|
894
|
-
lock_guard<boost::mutex> l(syncher);
|
894
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
895
895
|
P_WARN("Timeout trying to communicate with the logging agent at " << serverAddress << "; " <<
|
896
896
|
"will reconnect in " << reconnectTimeout / 1000000 << " second(s).");
|
897
897
|
nextReconnectTime = SystemTime::getUsec() + reconnectTimeout;
|
@@ -904,7 +904,7 @@ public:
|
|
904
904
|
|
905
905
|
guard.clear();
|
906
906
|
gotErrorResponse = connection->disconnect(errorResponse);
|
907
|
-
lock_guard<boost::mutex> l(syncher);
|
907
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
908
908
|
if (gotErrorResponse) {
|
909
909
|
P_WARN("The logging agent at " << serverAddress <<
|
910
910
|
" closed the connection (error message: " << errorResponse <<
|
@@ -925,12 +925,12 @@ public:
|
|
925
925
|
}
|
926
926
|
|
927
927
|
void setMaxConnectTries(unsigned int value) {
|
928
|
-
lock_guard<boost::mutex> l(syncher);
|
928
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
929
929
|
maxConnectTries = value;
|
930
930
|
}
|
931
931
|
|
932
932
|
void setReconnectTimeout(unsigned long long usec) {
|
933
|
-
lock_guard<boost::mutex> l(syncher);
|
933
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
934
934
|
reconnectTimeout = usec;
|
935
935
|
}
|
936
936
|
|
data/ext/common/Utils.cpp
CHANGED
@@ -412,7 +412,7 @@ parseModeString(const StaticString &mode) {
|
|
412
412
|
|
413
413
|
if (clause.empty()) {
|
414
414
|
continue;
|
415
|
-
} else if (clause.size() < 2 || clause[1] != '=') {
|
415
|
+
} else if (clause.size() < 2 || (clause[0] != '+' && clause[1] != '=')) {
|
416
416
|
throw InvalidModeStringException("Invalid mode clause specification '" + clause + "'");
|
417
417
|
}
|
418
418
|
|
@@ -483,6 +483,20 @@ parseModeString(const StaticString &mode) {
|
|
483
483
|
}
|
484
484
|
}
|
485
485
|
break;
|
486
|
+
case '+':
|
487
|
+
for (string::size_type i = 1; i < clause.size(); i++) {
|
488
|
+
switch (clause[i]) {
|
489
|
+
case 't':
|
490
|
+
modeBits |= S_ISVTX;
|
491
|
+
break;
|
492
|
+
default:
|
493
|
+
throw InvalidModeStringException("Invalid permission '" +
|
494
|
+
string(1, clause[i]) +
|
495
|
+
"' in mode clause specification '" +
|
496
|
+
clause + "'");
|
497
|
+
}
|
498
|
+
}
|
499
|
+
break;
|
486
500
|
default:
|
487
501
|
throw InvalidModeStringException("Invalid owner '" + string(1, clause[0]) +
|
488
502
|
"' in mode clause specification '" + clause + "'");
|
@@ -962,12 +976,24 @@ runShellCommand(const StaticString &command) {
|
|
962
976
|
}
|
963
977
|
}
|
964
978
|
|
965
|
-
|
966
|
-
// http://
|
979
|
+
#ifdef __APPLE__
|
980
|
+
// http://www.opensource.apple.com/source/Libc/Libc-825.26/sys/fork.c
|
981
|
+
// This bypasses atfork handlers.
|
982
|
+
extern "C" {
|
983
|
+
extern pid_t __fork(void);
|
984
|
+
}
|
985
|
+
#endif
|
986
|
+
|
967
987
|
pid_t
|
968
988
|
asyncFork() {
|
969
989
|
#if defined(__linux__)
|
970
|
-
|
990
|
+
#if defined(SYS_fork)
|
991
|
+
return (pid_t) syscall(SYS_fork);
|
992
|
+
#else
|
993
|
+
return syscall(SYS_clone, SIGCHLD, 0, 0, 0, 0);
|
994
|
+
#endif
|
995
|
+
#elif defined(__APPLE__)
|
996
|
+
return __fork();
|
971
997
|
#else
|
972
998
|
return fork();
|
973
999
|
#endif
|
data/ext/common/Utils.h
CHANGED
@@ -413,7 +413,14 @@ int runShellCommand(const StaticString &command);
|
|
413
413
|
|
414
414
|
/**
|
415
415
|
* Async-signal safe way to fork().
|
416
|
+
*
|
417
|
+
* On Linux, the fork() glibc wrapper grabs a ptmalloc lock, so
|
418
|
+
* if malloc causes a segfault then we can't fork.
|
416
419
|
* http://sourceware.org/bugzilla/show_bug.cgi?id=4737
|
420
|
+
*
|
421
|
+
* OS X apparently does something similar, except they use a
|
422
|
+
* spinlock so it results in 100% CPU. See _cthread_fork_prepare()
|
423
|
+
* at http://www.opensource.apple.com/source/Libc/Libc-166/threads.subproj/cthreads.c
|
417
424
|
*/
|
418
425
|
pid_t asyncFork();
|
419
426
|
|
@@ -53,7 +53,7 @@ public:
|
|
53
53
|
}
|
54
54
|
|
55
55
|
unsigned int size() const {
|
56
|
-
lock_guard<timed_mutex> l(lock);
|
56
|
+
boost::lock_guard<timed_mutex> l(lock);
|
57
57
|
return queue.size();
|
58
58
|
}
|
59
59
|
|
@@ -70,7 +70,7 @@ public:
|
|
70
70
|
}
|
71
71
|
|
72
72
|
bool tryAdd(const T &item) {
|
73
|
-
lock_guard<timed_mutex> l(lock);
|
73
|
+
boost::lock_guard<timed_mutex> l(lock);
|
74
74
|
if (!atMaxCapacity()) {
|
75
75
|
queue.push(item);
|
76
76
|
added.notify_one();
|
data/ext/common/Utils/Lock.h
CHANGED
@@ -8,8 +8,8 @@ namespace Passenger {
|
|
8
8
|
using namespace boost;
|
9
9
|
|
10
10
|
/** Shortcut typedefs. */
|
11
|
-
typedef lock_guard<boost::mutex> LockGuard;
|
12
|
-
typedef unique_lock<boost::mutex> ScopedLock;
|
11
|
+
typedef boost::lock_guard<boost::mutex> LockGuard;
|
12
|
+
typedef boost::unique_lock<boost::mutex> ScopedLock;
|
13
13
|
|
14
14
|
/** Nicer syntax for conditionally locking the mutex during construction. */
|
15
15
|
class DynamicScopedLock: public unique_lock<boost::mutex> {
|
@@ -198,7 +198,7 @@ class MessageBox: public enable_shared_from_this<MessageBox> {
|
|
198
198
|
|
199
199
|
public:
|
200
200
|
void send(const MessagePtr &message) {
|
201
|
-
lock_guard<boost::mutex> l(syncher);
|
201
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
202
202
|
message->setFrom(shared_from_this());
|
203
203
|
messages.push_back(message);
|
204
204
|
cond.notify_all();
|
@@ -287,7 +287,7 @@ public:
|
|
287
287
|
}
|
288
288
|
|
289
289
|
unsigned int size() const {
|
290
|
-
lock_guard<boost::mutex> l(syncher);
|
290
|
+
boost::lock_guard<boost::mutex> l(syncher);
|
291
291
|
return messages.size();
|
292
292
|
}
|
293
293
|
};
|
data/ext/common/Utils/Timer.h
CHANGED
@@ -74,7 +74,7 @@ public:
|
|
74
74
|
// TODO: We really use should clock_gettime() and the monotonic
|
75
75
|
// clock whenever possible, instead of gettimeofday()...
|
76
76
|
// On OS X we can use mach_absolute_time()
|
77
|
-
lock_guard<boost::mutex> l(lock);
|
77
|
+
boost::lock_guard<boost::mutex> l(lock);
|
78
78
|
int ret;
|
79
79
|
do {
|
80
80
|
ret = gettimeofday(&startTime, NULL);
|
@@ -87,7 +87,7 @@ public:
|
|
87
87
|
* and sufficient amount of time has elapsed.
|
88
88
|
*/
|
89
89
|
void stop() {
|
90
|
-
lock_guard<boost::mutex> l(lock);
|
90
|
+
boost::lock_guard<boost::mutex> l(lock);
|
91
91
|
startTime.tv_sec = 0;
|
92
92
|
startTime.tv_usec = 0;
|
93
93
|
}
|
@@ -97,7 +97,7 @@ public:
|
|
97
97
|
* in miliseconds. If the timer is currently stopped, then 0 is returned.
|
98
98
|
*/
|
99
99
|
unsigned long long elapsed() const {
|
100
|
-
lock_guard<boost::mutex> l(lock);
|
100
|
+
boost::lock_guard<boost::mutex> l(lock);
|
101
101
|
if (startTime.tv_sec == 0 && startTime.tv_usec == 0) {
|
102
102
|
return 0;
|
103
103
|
} else {
|
@@ -119,7 +119,7 @@ public:
|
|
119
119
|
* in microseconds. If the timer is currently stopped, then 0 is returned.
|
120
120
|
*/
|
121
121
|
unsigned long long usecElapsed() const {
|
122
|
-
lock_guard<boost::mutex> l(lock);
|
122
|
+
boost::lock_guard<boost::mutex> l(lock);
|
123
123
|
if (startTime.tv_sec == 0 && startTime.tv_usec == 0) {
|
124
124
|
return 0;
|
125
125
|
} else {
|
@@ -53,6 +53,7 @@ struct AgentOptions {
|
|
53
53
|
string exitPassword;
|
54
54
|
string loggingAgentAddress;
|
55
55
|
string loggingAgentPassword;
|
56
|
+
string adminToolStatusPassword;
|
56
57
|
vector<string> prestartUrls;
|
57
58
|
|
58
59
|
string requestSocketLink;
|
@@ -84,6 +85,7 @@ struct AgentOptions {
|
|
84
85
|
exitPassword = options.get("helper_agent_exit_password");
|
85
86
|
loggingAgentAddress = options.get("logging_agent_address");
|
86
87
|
loggingAgentPassword = options.get("logging_agent_password");
|
88
|
+
adminToolStatusPassword = options.get("admin_tool_status_password");
|
87
89
|
|
88
90
|
// Optional options.
|
89
91
|
prestartUrls = options.getStrSet("prestart_urls", false);
|
@@ -51,7 +51,6 @@
|
|
51
51
|
|
52
52
|
#include <agents/HelperAgent/RequestHandler.h>
|
53
53
|
#include <agents/HelperAgent/RequestHandler.cpp>
|
54
|
-
#include <agents/HelperAgent/BacktracesServer.h>
|
55
54
|
#include <agents/HelperAgent/AgentOptions.h>
|
56
55
|
|
57
56
|
#include <agents/Base.h>
|
@@ -85,6 +84,7 @@ private:
|
|
85
84
|
|
86
85
|
typedef MessageServer::CommonClientContext CommonClientContext;
|
87
86
|
|
87
|
+
shared_ptr<RequestHandler> requestHandler;
|
88
88
|
PoolPtr pool;
|
89
89
|
|
90
90
|
|
@@ -92,17 +92,30 @@ private:
|
|
92
92
|
* Message handler methods
|
93
93
|
*********************************************/
|
94
94
|
|
95
|
-
void
|
95
|
+
void processDetachProcess(CommonClientContext &commonContext, SpecificContext *specificContext,
|
96
|
+
const vector<string> &args)
|
97
|
+
{
|
96
98
|
TRACE_POINT();
|
97
99
|
commonContext.requireRights(Account::DETACH);
|
98
|
-
|
100
|
+
if (pool->detachProcess((pid_t) atoi(args[1]))) {
|
99
101
|
writeArrayMessage(commonContext.fd, "true", NULL);
|
100
|
-
} else {
|
102
|
+
} else {
|
101
103
|
writeArrayMessage(commonContext.fd, "false", NULL);
|
102
|
-
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
void processDetachProcessByKey(CommonClientContext &commonContext, SpecificContext *specificContext,
|
108
|
+
const vector<string> &args)
|
109
|
+
{
|
110
|
+
TRACE_POINT();
|
111
|
+
commonContext.requireRights(Account::DETACH);
|
112
|
+
// TODO: implement this
|
113
|
+
writeArrayMessage(commonContext.fd, "false", NULL);
|
103
114
|
}
|
104
115
|
|
105
|
-
bool processInspect(CommonClientContext &commonContext, SpecificContext *specificContext,
|
116
|
+
bool processInspect(CommonClientContext &commonContext, SpecificContext *specificContext,
|
117
|
+
const vector<string> &args)
|
118
|
+
{
|
106
119
|
TRACE_POINT();
|
107
120
|
commonContext.requireRights(Account::INSPECT_BASIC_INFO);
|
108
121
|
if ((args.size() - 1) % 2 != 0) {
|
@@ -123,7 +136,9 @@ private:
|
|
123
136
|
return true;
|
124
137
|
}
|
125
138
|
|
126
|
-
void processToXml(CommonClientContext &commonContext, SpecificContext *specificContext,
|
139
|
+
void processToXml(CommonClientContext &commonContext, SpecificContext *specificContext,
|
140
|
+
const vector<string> &args)
|
141
|
+
{
|
127
142
|
TRACE_POINT();
|
128
143
|
commonContext.requireRights(Account::INSPECT_BASIC_INFO);
|
129
144
|
bool includeSensitiveInfo =
|
@@ -131,9 +146,28 @@ private:
|
|
131
146
|
args[1] == "true";
|
132
147
|
writeScalarMessage(commonContext.fd, pool->toXml(includeSensitiveInfo));
|
133
148
|
}
|
149
|
+
|
150
|
+
void processBacktraces(CommonClientContext &commonContext, SpecificContext *specificContext,
|
151
|
+
const vector<string> &args)
|
152
|
+
{
|
153
|
+
TRACE_POINT();
|
154
|
+
commonContext.requireRights(Account::INSPECT_BACKTRACES);
|
155
|
+
writeScalarMessage(commonContext.fd, oxt::thread::all_backtraces());
|
156
|
+
}
|
157
|
+
|
158
|
+
void processRequests(CommonClientContext &commonContext, SpecificContext *specificContext,
|
159
|
+
const vector<string> &args)
|
160
|
+
{
|
161
|
+
TRACE_POINT();
|
162
|
+
stringstream stream;
|
163
|
+
commonContext.requireRights(Account::INSPECT_REQUESTS);
|
164
|
+
requestHandler->inspect(stream);
|
165
|
+
writeScalarMessage(commonContext.fd, stream.str());
|
166
|
+
}
|
134
167
|
|
135
168
|
public:
|
136
|
-
RemoteController(const PoolPtr &pool) {
|
169
|
+
RemoteController(const shared_ptr<RequestHandler> &requestHandler, const PoolPtr &pool) {
|
170
|
+
this->requestHandler = requestHandler;
|
137
171
|
this->pool = pool;
|
138
172
|
}
|
139
173
|
|
@@ -147,12 +181,18 @@ public:
|
|
147
181
|
{
|
148
182
|
SpecificContext *specificContext = (SpecificContext *) _specificContext.get();
|
149
183
|
try {
|
150
|
-
if (args[0] == "
|
151
|
-
|
184
|
+
if (args[0] == "detach_process" && args.size() == 2) {
|
185
|
+
processDetachProcess(commonContext, specificContext, args);
|
186
|
+
} else if (args[0] == "detach_process_by_key" && args.size() == 2) {
|
187
|
+
processDetachProcessByKey(commonContext, specificContext, args);
|
152
188
|
} else if (args[0] == "inspect") {
|
153
189
|
return processInspect(commonContext, specificContext, args);
|
154
190
|
} else if (args[0] == "toXml" && args.size() == 2) {
|
155
191
|
processToXml(commonContext, specificContext, args);
|
192
|
+
} else if (args[0] == "backtraces") {
|
193
|
+
processBacktraces(commonContext, specificContext, args);
|
194
|
+
} else if (args[0] == "requests") {
|
195
|
+
processRequests(commonContext, specificContext, args);
|
156
196
|
} else {
|
157
197
|
return false;
|
158
198
|
}
|
@@ -381,8 +421,10 @@ public:
|
|
381
421
|
UPDATE_TRACE_POINT();
|
382
422
|
generation = serverInstanceDir.getGeneration(options.generationNumber);
|
383
423
|
startListening();
|
384
|
-
accountsDatabase = AccountsDatabase
|
385
|
-
|
424
|
+
accountsDatabase = make_shared<AccountsDatabase>();
|
425
|
+
accountsDatabase->add("_passenger-status", options.adminToolStatusPassword, false,
|
426
|
+
Account::INSPECT_BASIC_INFO | Account::INSPECT_SENSITIVE_INFO |
|
427
|
+
Account::INSPECT_BACKTRACES | Account::INSPECT_REQUESTS);
|
386
428
|
accountsDatabase->add("_web_server", options.exitPassword, false, Account::EXIT);
|
387
429
|
messageServer = make_shared<MessageServer>(
|
388
430
|
parseUnixSocketAddress(options.adminSocketAddress), accountsDatabase);
|
@@ -415,13 +457,12 @@ public:
|
|
415
457
|
//pool->setMaxPerApp(maxInstancesPerApp);
|
416
458
|
pool->setMaxIdleTime(options.poolIdleTime * 1000000);
|
417
459
|
|
418
|
-
messageServer->addHandler(make_shared<RemoteController>(pool));
|
419
|
-
messageServer->addHandler(make_shared<BacktracesServer>());
|
420
|
-
messageServer->addHandler(ptr(new ExitHandler(exitEvent)));
|
421
|
-
|
422
460
|
requestHandler = make_shared<RequestHandler>(requestLoop.safe,
|
423
461
|
requestSocket, pool, options);
|
424
462
|
|
463
|
+
messageServer->addHandler(make_shared<RemoteController>(requestHandler, pool));
|
464
|
+
messageServer->addHandler(ptr(new ExitHandler(exitEvent)));
|
465
|
+
|
425
466
|
sigquitWatcher.set(requestLoop.loop);
|
426
467
|
sigquitWatcher.set(SIGQUIT);
|
427
468
|
sigquitWatcher.set<Server, &Server::onSigquit>(this);
|
@@ -398,6 +398,8 @@ public:
|
|
398
398
|
timeoutTimer.stop();
|
399
399
|
|
400
400
|
freeScopeLogs();
|
401
|
+
|
402
|
+
requestHandler = NULL;
|
401
403
|
}
|
402
404
|
|
403
405
|
bool reassociateable() const {
|
@@ -507,7 +509,8 @@ public:
|
|
507
509
|
if (session == NULL) {
|
508
510
|
stream << indent << "session = NULL\n";
|
509
511
|
} else {
|
510
|
-
stream << indent << "session pid = " << session->getPid() << "
|
512
|
+
stream << indent << "session pid = " << session->getPid() << " (" <<
|
513
|
+
session->getGroup()->name << ")\n";
|
511
514
|
stream << indent << "session gupid = " << session->getGupid() << "\n";
|
512
515
|
stream << indent << "session initiated = " << boolStr(session->initiated()) << "\n";
|
513
516
|
}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2013 Phusion
|
4
|
+
*
|
5
|
+
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
|
+
*
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
12
|
+
* furnished to do so, subject to the following conditions:
|
13
|
+
*
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
15
|
+
* all copies or substantial portions of the Software.
|
16
|
+
*
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
* THE SOFTWARE.
|
24
|
+
*/
|
25
|
+
#ifndef _PASSENGER_ADMIN_CONTROLLER_H_
|
26
|
+
#define _PASSENGER_ADMIN_CONTROLLER_H_
|
27
|
+
|
28
|
+
|
29
|
+
#include <agents/LoggingAgent/LoggingServer.h>
|
30
|
+
#include <MessageServer.h>
|
31
|
+
#include <sstream>
|
32
|
+
|
33
|
+
namespace Passenger {
|
34
|
+
|
35
|
+
using namespace std;
|
36
|
+
using namespace boost;
|
37
|
+
using namespace oxt;
|
38
|
+
|
39
|
+
|
40
|
+
class AdminController: public MessageServer::Handler {
|
41
|
+
private:
|
42
|
+
struct SpecificContext: public MessageServer::ClientContext {
|
43
|
+
};
|
44
|
+
|
45
|
+
typedef MessageServer::CommonClientContext CommonClientContext;
|
46
|
+
|
47
|
+
const LoggingServer *server;
|
48
|
+
|
49
|
+
|
50
|
+
/*********************************************
|
51
|
+
* Message handler methods
|
52
|
+
*********************************************/
|
53
|
+
|
54
|
+
void processStatus(CommonClientContext &commonContext, SpecificContext *specificContext, const vector<string> &args) {
|
55
|
+
TRACE_POINT();
|
56
|
+
stringstream stream;
|
57
|
+
server->dump(stream);
|
58
|
+
writeScalarMessage(commonContext.fd, stream.str());
|
59
|
+
}
|
60
|
+
|
61
|
+
bool isCommand(const vector<string> &args, const string &command, unsigned int nargs = 0) const {
|
62
|
+
return args.size() == nargs + 1 && args[0] == command;
|
63
|
+
}
|
64
|
+
|
65
|
+
public:
|
66
|
+
AdminController(const LoggingServer *server) {
|
67
|
+
this->server = server;
|
68
|
+
}
|
69
|
+
|
70
|
+
virtual MessageServer::ClientContextPtr newClient(CommonClientContext &commonContext) {
|
71
|
+
return make_shared<SpecificContext>();
|
72
|
+
}
|
73
|
+
|
74
|
+
virtual bool processMessage(CommonClientContext &commonContext,
|
75
|
+
MessageServer::ClientContextPtr &_specificContext,
|
76
|
+
const vector<string> &args)
|
77
|
+
{
|
78
|
+
SpecificContext *specificContext = (SpecificContext *) _specificContext.get();
|
79
|
+
if (isCommand(args, "status", 0)) {
|
80
|
+
processStatus(commonContext, specificContext, args);
|
81
|
+
} else {
|
82
|
+
return false;
|
83
|
+
}
|
84
|
+
return true;
|
85
|
+
}
|
86
|
+
};
|
87
|
+
|
88
|
+
|
89
|
+
} // namespace Passenger
|
90
|
+
|
91
|
+
#endif /* _PASSENGER_ADMIN_CONTROLLER_H_ */
|