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.

Files changed (162) hide show
  1. data.tar.gz.asc +7 -7
  2. data/.travis.yml +1 -2
  3. data/CONTRIBUTING.md +20 -5
  4. data/CONTRIBUTORS +67 -0
  5. data/LICENSE +1 -1
  6. data/NEWS +48 -0
  7. data/Rakefile +2 -2
  8. data/bin/passenger-config +18 -0
  9. data/bin/passenger-install-apache2-module +2 -0
  10. data/bin/passenger-install-nginx-module +11 -12
  11. data/bin/passenger-memory-stats +2 -0
  12. data/bin/passenger-status +152 -69
  13. data/build/agents.rb +1 -5
  14. data/build/basics.rb +26 -13
  15. data/build/cplusplus_support.rb +9 -0
  16. data/build/debian.rb +129 -0
  17. data/build/documentation.rb +6 -2
  18. data/build/integration_tests.rb +13 -2
  19. data/build/misc.rb +16 -0
  20. data/build/packaging.rb +67 -51
  21. data/build/preprocessor.rb +314 -0
  22. data/build/test_basics.rb +1 -0
  23. data/{debian → debian.template}/README.Debian +0 -0
  24. data/{debian → debian.template}/changelog +131 -0
  25. data/debian.template/compat +1 -0
  26. data/debian.template/control +71 -0
  27. data/debian.template/copyright +385 -0
  28. data/debian.template/libapache2-mod-passenger.install +3 -0
  29. data/{debian → debian.template}/libapache2-mod-passenger.postinst +0 -0
  30. data/{debian → debian.template}/libapache2-mod-passenger.prerm +0 -0
  31. data/debian.template/locations.ini +12 -0
  32. data/debian.template/passenger.conf +4 -0
  33. data/{debian → debian.template}/passenger.load +0 -0
  34. data/debian.template/patches/series +0 -0
  35. data/debian.template/repack.sh +42 -0
  36. data/debian.template/ruby-passenger-dev.install +3 -0
  37. data/debian.template/ruby-passenger-doc.install +2 -0
  38. data/debian.template/ruby-passenger.docs +4 -0
  39. data/debian.template/ruby-passenger.install +11 -0
  40. data/debian.template/ruby-passenger.manpages +4 -0
  41. data/debian.template/rules.template +35 -0
  42. data/debian.template/source/format +1 -0
  43. data/debian.template/watch +3 -0
  44. data/dev/run_travis.sh +46 -46
  45. data/doc/Architectural overview.html +2 -2
  46. data/doc/Packaging.html +27 -18
  47. data/doc/Packaging.txt.md +27 -18
  48. data/doc/Security of user switching support.html +2 -2
  49. data/doc/Users guide Apache.html +881 -95
  50. data/doc/Users guide Apache.idmap.txt +48 -6
  51. data/doc/Users guide Apache.txt +13 -1
  52. data/doc/Users guide Nginx.html +1063 -190
  53. data/doc/Users guide Nginx.idmap.txt +89 -45
  54. data/doc/Users guide Nginx.txt +45 -0
  55. data/doc/Users guide Standalone.html +7 -7
  56. data/doc/users_guide_snippets/alternative_for_flying_passenger.txt +1 -0
  57. data/doc/users_guide_snippets/environment_variables.txt +221 -0
  58. data/doc/users_guide_snippets/installation.txt +66 -17
  59. data/doc/users_guide_snippets/support_information.txt +3 -3
  60. data/doc/users_guide_snippets/tips.txt +352 -40
  61. data/ext/common/Account.h +4 -3
  62. data/ext/common/AccountsDatabase.h +6 -6
  63. data/ext/common/AgentsStarter.h +1 -13
  64. data/ext/common/ApplicationPool2/DirectSpawner.h +4 -4
  65. data/ext/common/ApplicationPool2/DummySpawner.h +1 -1
  66. data/ext/common/ApplicationPool2/Group.h +9 -4
  67. data/ext/common/ApplicationPool2/Implementation.cpp +6 -1
  68. data/ext/common/ApplicationPool2/Options.h +65 -37
  69. data/ext/common/ApplicationPool2/Pool.h +91 -41
  70. data/ext/common/ApplicationPool2/Process.h +6 -6
  71. data/ext/common/ApplicationPool2/SmartSpawner.h +14 -14
  72. data/ext/common/ApplicationPool2/Socket.h +1 -1
  73. data/ext/common/ApplicationPool2/Spawner.h +24 -16
  74. data/ext/common/ApplicationPool2/SpawnerFactory.h +9 -1
  75. data/ext/common/ApplicationPool2/SuperGroup.h +1 -1
  76. data/ext/common/Constants.h +1 -1
  77. data/ext/common/Logging.cpp +12 -7
  78. data/ext/common/MessageServer.h +7 -12
  79. data/ext/common/MultiLibeio.cpp +5 -5
  80. data/ext/common/ResourceLocator.h +2 -6
  81. data/ext/common/ServerInstanceDir.h +37 -10
  82. data/ext/common/UnionStation.h +10 -10
  83. data/ext/common/Utils.cpp +30 -4
  84. data/ext/common/Utils.h +7 -0
  85. data/ext/common/Utils/BlockingQueue.h +2 -2
  86. data/ext/common/Utils/Lock.h +2 -2
  87. data/ext/common/Utils/MessagePassing.h +2 -2
  88. data/ext/common/Utils/Timer.h +4 -4
  89. data/ext/common/agents/HelperAgent/AgentOptions.h +2 -0
  90. data/ext/common/agents/HelperAgent/Main.cpp +57 -16
  91. data/ext/common/agents/HelperAgent/RequestHandler.h +4 -1
  92. data/ext/common/agents/LoggingAgent/AdminController.h +91 -0
  93. data/ext/common/agents/LoggingAgent/LoggingServer.h +46 -29
  94. data/ext/common/agents/LoggingAgent/Main.cpp +43 -16
  95. data/ext/common/agents/LoggingAgent/RemoteSender.h +7 -7
  96. data/ext/common/agents/Watchdog/AgentWatcher.cpp +11 -11
  97. data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +3 -1
  98. data/ext/common/agents/Watchdog/Main.cpp +62 -0
  99. data/ext/libeio/config.guess +206 -167
  100. data/ext/libeio/config.sub +142 -68
  101. data/ext/libev/config.guess +304 -290
  102. data/ext/libev/config.sub +198 -77
  103. data/ext/nginx/config +4 -0
  104. data/ext/nginx/ngx_http_passenger_module.c +1 -0
  105. data/ext/oxt/implementation.cpp +4 -4
  106. data/lib/phusion_passenger.rb +14 -5
  107. data/lib/phusion_passenger/abstract_installer.rb +41 -0
  108. data/lib/phusion_passenger/admin_tools/server_instance.rb +48 -39
  109. data/lib/phusion_passenger/message_client.rb +31 -7
  110. data/lib/phusion_passenger/native_support.rb +35 -12
  111. data/lib/phusion_passenger/packaging.rb +16 -2
  112. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +6 -31
  113. data/lib/phusion_passenger/platform_info/operating_system.rb +1 -1
  114. data/lib/phusion_passenger/preloader_shared_helpers.rb +3 -1
  115. data/lib/phusion_passenger/request_handler.rb +1 -1
  116. data/lib/phusion_passenger/standalone/command.rb +6 -6
  117. data/lib/phusion_passenger/standalone/main.rb +23 -8
  118. data/lib/phusion_passenger/standalone/package_runtime_command.rb +9 -5
  119. data/lib/phusion_passenger/standalone/runtime_installer.rb +9 -10
  120. data/lib/phusion_passenger/standalone/start_command.rb +20 -4
  121. data/resources/templates/installer_common/freebsd9_broken_cxx_runtime.txt.erb +19 -0
  122. data/resources/templates/installer_common/low_amount_of_memory_warning.txt.erb +22 -0
  123. data/resources/templates/standalone/config.erb +3 -2
  124. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +4 -4
  125. data/test/cxx/ApplicationPool2/PoolTest.cpp +1 -1
  126. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +7 -7
  127. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +9 -9
  128. data/test/cxx/EventedBufferedInputTest.cpp +17 -17
  129. data/test/cxx/RequestHandlerTest.cpp +5 -5
  130. data/test/cxx/ServerInstanceDirTest.cpp +3 -1
  131. data/test/cxx/TestSupport.h +4 -4
  132. data/test/cxx/UnionStationTest.cpp +3 -1
  133. data/test/cxx/UtilsTest.cpp +2 -0
  134. data/test/integration_tests/apache2_tests.rb +2 -2
  135. data/test/integration_tests/native_packaging_spec.rb +170 -0
  136. data/test/ruby/spec_helper.rb +0 -1
  137. data/test/stub/apache2/httpd.conf.erb +1 -1
  138. data/test/stub/nginx/nginx.conf.erb +1 -0
  139. data/test/support/apache2_controller.rb +1 -1
  140. data/test/support/placebo-preloader.rb +1 -1
  141. data/test/support/test_helper.rb +5 -2
  142. metadata +32 -26
  143. metadata.gz.asc +7 -7
  144. data/debian/compat +0 -1
  145. data/debian/control +0 -49
  146. data/debian/copyright +0 -20
  147. data/debian/libapache2-mod-passenger.install +0 -1
  148. data/debian/passenger-common.install +0 -4
  149. data/debian/passenger.conf +0 -4
  150. data/debian/prerm +0 -2
  151. data/debian/rules +0 -37
  152. data/debian/watch +0 -3
  153. data/dev/googlecode_upload.py +0 -265
  154. data/ext/common/agents/HelperAgent/BacktracesServer.h +0 -60
  155. data/resources/templates/nginx/not_available_when_natively_packaged.txt.erb +0 -8
  156. data/test/stub/rails3.1/app/assets/javascripts/application.js +0 -9
  157. data/test/stub/rails3.2/app/assets/javascripts/application.js +0 -15
  158. data/test/stub/rails_apps/2.3/mycook/public/javascripts/application.js +0 -2
  159. data/test/stub/rails_apps/2.3/mycook/public/javascripts/controls.js +0 -963
  160. data/test/stub/rails_apps/2.3/mycook/public/javascripts/dragdrop.js +0 -973
  161. data/test/stub/rails_apps/2.3/mycook/public/javascripts/effects.js +0 -1128
  162. data/test/stub/rails_apps/2.3/mycook/public/javascripts/prototype.js +0 -4320
@@ -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
 
@@ -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
- // Async-signal safe way to fork().
966
- // http://sourceware.org/bugzilla/show_bug.cgi?id=4737
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
- return (pid_t) syscall(SYS_fork);
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
@@ -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();
@@ -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
  };
@@ -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 processDetach(CommonClientContext &commonContext, SpecificContext *specificContext, const vector<string> &args) {
95
+ void processDetachProcess(CommonClientContext &commonContext, SpecificContext *specificContext,
96
+ const vector<string> &args)
97
+ {
96
98
  TRACE_POINT();
97
99
  commonContext.requireRights(Account::DETACH);
98
- /* if (pool->detach(args[1])) {
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, const vector<string> &args) {
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, const vector<string> &args) {
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] == "detach" && args.size() == 2) {
151
- processDetach(commonContext, specificContext, args);
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::createDefault(generation,
385
- options.userSwitching, options.defaultUser, options.defaultGroup);
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() << "\n";
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_ */