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
@@ -56,6 +56,7 @@
56
56
  #include <Utils/MD5.h>
57
57
  #include <Utils/IOUtils.h>
58
58
  #include <Utils/MessageIO.h>
59
+ #include <Utils/VariantMap.h>
59
60
  #include <Utils/StrIntUtils.h>
60
61
  #include <Utils/StringMap.h>
61
62
 
@@ -119,10 +120,20 @@ private:
119
120
  virtual bool isRemote() const {
120
121
  return false;
121
122
  }
123
+
124
+ // Default interval at which this sink should be flushed.
125
+ virtual unsigned int defaultFlushInterval() const {
126
+ return 15;
127
+ }
122
128
 
123
129
  virtual void append(const DataStoreId &dataStoreId,
124
130
  const StaticString &data) = 0;
125
- virtual bool flush() { return true; }
131
+
132
+ virtual bool flush() {
133
+ lastFlushed = ev_now(server->getLoop());
134
+ return true;
135
+ }
136
+
126
137
  virtual void dump(ostream &stream) const { }
127
138
  };
128
139
 
@@ -154,12 +165,7 @@ private:
154
165
  virtual void append(const DataStoreId &dataStoreId, const StaticString &data) {
155
166
  syscalls::write(fd, data.data(), data.size());
156
167
  }
157
-
158
- virtual bool flush() {
159
- lastFlushed = ev_now(server->getLoop());
160
- return true;
161
- }
162
-
168
+
163
169
  virtual void dump(ostream &stream) const {
164
170
  stream << " * Log file: " << filename << "\n";
165
171
  stream << " Opened : " << opened << "\n";
@@ -211,6 +217,10 @@ private:
211
217
  virtual bool isRemote() const {
212
218
  return true;
213
219
  }
220
+
221
+ virtual unsigned int defaultFlushInterval() const {
222
+ return 60;
223
+ }
214
224
 
215
225
  virtual void append(const DataStoreId &dataStoreId, const StaticString &data) {
216
226
  if (bufferSize + data.size() > BUFFER_CAPACITY) {
@@ -235,11 +245,17 @@ private:
235
245
  server->remoteSender.schedule(unionStationKey, nodeName,
236
246
  category, &data, 1);
237
247
  bufferSize = 0;
248
+ P_DEBUG("Flushed remote sink " << inspect() << ": " << bufferSize << " bytes");
238
249
  return true;
239
250
  } else {
251
+ P_DEBUG("Flushed remote sink " << inspect() << ": 0 bytes");
240
252
  return false;
241
253
  }
242
254
  }
255
+
256
+ string inspect() const {
257
+ return "(key=" + unionStationKey + ", node=" + nodeName + ", category=" + category + ")";
258
+ }
243
259
 
244
260
  virtual void dump(ostream &stream) const {
245
261
  stream << " * Remote sink\n";
@@ -369,7 +385,6 @@ private:
369
385
 
370
386
  typedef shared_ptr<FilterSupport::Filter> FilterPtr;
371
387
 
372
- string dumpFile;
373
388
  RemoteSender remoteSender;
374
389
  ev::timer garbageCollectionTimer;
375
390
  ev::timer sinkFlushingTimer;
@@ -390,6 +405,8 @@ private:
390
405
  bool refuseNewConnections;
391
406
  bool exitRequested;
392
407
  unsigned long long exitBeginTime;
408
+ int sinkFlushInterval;
409
+ string dumpFile;
393
410
 
394
411
  void sendErrorToClient(Client *client, const string &message) {
395
412
  client->writeArrayMessage("error", message.c_str(), NULL);
@@ -703,23 +720,24 @@ private:
703
720
  P_DEBUG("Garbage collection time");
704
721
  releaseInactiveLogSinks(ev_now(getLoop()));
705
722
  }
723
+
724
+ ev_tstamp getFlushInterval(const LogSink *sink) const {
725
+ if (sinkFlushInterval == 0) {
726
+ return sink->defaultFlushInterval();
727
+ } else {
728
+ return sinkFlushInterval;
729
+ }
730
+ }
706
731
 
707
732
  void sinkFlushTimeout(ev::timer &timer, int revents) {
708
- P_TRACE(2, "Flushing all sinks (periodic action)");
733
+ P_DEBUG("Flushing all sinks");
709
734
  LogSinkCache::iterator it;
710
735
  LogSinkCache::iterator end = logSinkCache.end();
711
736
  ev_tstamp now = ev_now(getLoop());
712
737
 
713
738
  for (it = logSinkCache.begin(); it != end; it++) {
714
739
  LogSink *sink = it->second.get();
715
-
716
- // Flush log file sinks every 15 seconds,
717
- // remote sinks every 60 seconds.
718
- if (sink->isRemote()) {
719
- if (now - sink->lastFlushed >= 60) {
720
- sink->flush();
721
- }
722
- } else {
740
+ if (now - sink->lastFlushed >= getFlushInterval(sink)) {
723
741
  sink->flush();
724
742
  }
725
743
  }
@@ -1080,25 +1098,24 @@ public:
1080
1098
  LoggingServer(struct ev_loop *loop,
1081
1099
  FileDescriptor fd,
1082
1100
  const AccountsDatabasePtr &accountsDatabase,
1083
- const string &dumpFile,
1084
- const string &unionStationGatewayAddress = DEFAULT_UNION_STATION_GATEWAY_ADDRESS,
1085
- unsigned short unionStationGatewayPort = DEFAULT_UNION_STATION_GATEWAY_PORT,
1086
- const string &unionStationGatewayCert = "",
1087
- const string &unionStationProxyAddress = "")
1101
+ const VariantMap &options = VariantMap()/**/)
1088
1102
  : EventedMessageServer(loop, fd, accountsDatabase),
1089
- remoteSender(unionStationGatewayAddress,
1090
- unionStationGatewayPort,
1091
- unionStationGatewayCert,
1092
- unionStationProxyAddress),
1103
+ remoteSender(
1104
+ options.get("union_station_gateway_address", false, DEFAULT_UNION_STATION_GATEWAY_ADDRESS),
1105
+ options.getInt("union_station_gateway_port", false, DEFAULT_UNION_STATION_GATEWAY_PORT),
1106
+ options.get("union_station_gateway_cert", false, ""),
1107
+ options.get("union_station_proxy_address", false)),
1093
1108
  garbageCollectionTimer(loop),
1094
1109
  sinkFlushingTimer(loop),
1095
- exitTimer(loop)
1110
+ exitTimer(loop),
1111
+ dumpFile(options.get("analytics_dump_file", false, "/dev/null"))
1096
1112
  {
1097
- this->dumpFile = dumpFile;
1113
+ int sinkFlushTimerInterval = options.getInt("analytics_sink_flush_timer_interval", false, 15);
1114
+ sinkFlushInterval = options.getInt("analytics_sink_flush_interval", false, 0);
1098
1115
  garbageCollectionTimer.set<LoggingServer, &LoggingServer::garbageCollect>(this);
1099
1116
  garbageCollectionTimer.start(GARBAGE_COLLECTION_TIMEOUT, GARBAGE_COLLECTION_TIMEOUT);
1100
1117
  sinkFlushingTimer.set<LoggingServer, &LoggingServer::sinkFlushTimeout>(this);
1101
- sinkFlushingTimer.start(15, 15);
1118
+ sinkFlushingTimer.start(sinkFlushTimerInterval, sinkFlushTimerInterval);
1102
1119
  exitTimer.set<LoggingServer, &LoggingServer::exitTimerTimeout>(this);
1103
1120
  exitTimer.set(0.05, 0.05);
1104
1121
  refuseNewConnections = false;
@@ -38,10 +38,13 @@
38
38
 
39
39
  #include <agents/Base.h>
40
40
  #include <agents/LoggingAgent/LoggingServer.h>
41
+ #include <agents/LoggingAgent/AdminController.h>
41
42
 
42
43
  #include <AccountsDatabase.h>
43
44
  #include <Account.h>
44
45
  #include <Exceptions.h>
46
+ #include <ResourceLocator.h>
47
+ #include <MessageServer.h>
45
48
  #include <Utils.h>
46
49
  #include <Utils/IOUtils.h>
47
50
  #include <Utils/MessageIO.h>
@@ -56,6 +59,9 @@ static struct ev_loop *eventLoop;
56
59
  static LoggingServer *loggingServer;
57
60
  static int exitCode = 0;
58
61
 
62
+ static const int MESSAGE_SERVER_THREAD_STACK_SIZE = 128 * 1024;
63
+
64
+
59
65
  static struct ev_loop *
60
66
  createEventLoop() {
61
67
  struct ev_loop *loop;
@@ -150,21 +156,29 @@ myself() {
150
156
  }
151
157
  }
152
158
 
159
+ static string
160
+ findUnionStationGatewayCert(const ResourceLocator &locator,
161
+ const string &cert)
162
+ {
163
+ if (cert.empty()) {
164
+ return locator.getResourcesDir() + "/union_station_gateway.crt";
165
+ } else if (cert != "-") {
166
+ return cert;
167
+ } else {
168
+ return "";
169
+ }
170
+ }
171
+
153
172
  int
154
173
  main(int argc, char *argv[]) {
155
174
  VariantMap options = initializeAgent(argc, argv, "PassengerLoggingAgent");
175
+ string passengerRoot = options.get("passenger_root");
156
176
  string socketAddress = options.get("logging_agent_address");
157
- string dumpFile = options.get("analytics_dump_file", false, "/dev/null");
177
+ string adminSocketAddress = options.get("logging_agent_admin_address");
158
178
  string password = options.get("logging_agent_password");
159
- string username = options.get("analytics_log_user",
160
- false, myself());
179
+ string username = options.get("analytics_log_user", false, myself());
161
180
  string groupname = options.get("analytics_log_group", false);
162
- string unionStationGatewayAddress = options.get("union_station_gateway_address",
163
- false, DEFAULT_UNION_STATION_GATEWAY_ADDRESS);
164
- int unionStationGatewayPort = options.getInt("union_station_gateway_port",
165
- false, DEFAULT_UNION_STATION_GATEWAY_PORT);
166
- string unionStationGatewayCert = options.get("union_station_gateway_cert", false);
167
- string unionStationProxyAddress = options.get("union_station_proxy_address", false);
181
+ string adminToolStatusPassword = options.get("admin_tool_status_password");
168
182
 
169
183
  curl_global_init(CURL_GLOBAL_ALL);
170
184
 
@@ -172,14 +186,19 @@ main(int argc, char *argv[]) {
172
186
  /********** Now begins the real initialization **********/
173
187
 
174
188
  /* Create all the necessary objects and sockets... */
175
- AccountsDatabasePtr accountsDatabase;
189
+ ResourceLocator resourceLocator(passengerRoot);
190
+ AccountsDatabasePtr accountsDatabase, adminAccountsDatabase;
176
191
  FileDescriptor serverSocketFd;
177
192
  struct passwd *user;
178
193
  struct group *group;
179
194
  int ret;
195
+
196
+ options.set("union_station_gateway_cert", findUnionStationGatewayCert(
197
+ resourceLocator, options.get("union_station_gateway_cert", false)));
180
198
 
181
199
  eventLoop = createEventLoop();
182
- accountsDatabase = ptr(new AccountsDatabase());
200
+ accountsDatabase = make_shared<AccountsDatabase>();
201
+ adminAccountsDatabase = make_shared<AccountsDatabase>();
183
202
  serverSocketFd = createServer(socketAddress.c_str());
184
203
  if (getSocketAddressType(socketAddress) == SAT_UNIX) {
185
204
  do {
@@ -240,12 +259,19 @@ main(int argc, char *argv[]) {
240
259
  /* Now setup the actual logging server. */
241
260
  accountsDatabase->add("logging", password, false);
242
261
  LoggingServer server(eventLoop, serverSocketFd,
243
- accountsDatabase, dumpFile,
244
- unionStationGatewayAddress,
245
- unionStationGatewayPort,
246
- unionStationGatewayCert,
247
- unionStationProxyAddress);
262
+ accountsDatabase, options);
248
263
  loggingServer = &server;
264
+
265
+ /* Setup the admin server. */
266
+ adminAccountsDatabase->add("_passenger-status", adminToolStatusPassword, false);
267
+ MessageServer adminServer(parseUnixSocketAddress(adminSocketAddress),
268
+ adminAccountsDatabase);
269
+ adminServer.addHandler(make_shared<AdminController>(&server));
270
+ function<void ()> adminServerFunc = boost::bind(&MessageServer::mainLoop, &adminServer);
271
+ oxt::thread adminServerThread(
272
+ boost::bind(runAndPrintExceptions, adminServerFunc, true),
273
+ "AdminServer thread", MESSAGE_SERVER_THREAD_STACK_SIZE
274
+ );
249
275
 
250
276
 
251
277
  ev::io feedbackFdWatcher(eventLoop);
@@ -270,6 +296,7 @@ main(int argc, char *argv[]) {
270
296
 
271
297
  P_WARN("PassengerLoggingAgent online, listening at " << socketAddress);
272
298
  ev_run(eventLoop, 0);
299
+ adminServerThread.interrupt_and_join();
273
300
  P_DEBUG("Logging agent exiting with code " << exitCode << ".");
274
301
  return exitCode;
275
302
  } catch (const tracable_exception &e) {
@@ -299,7 +299,7 @@ private:
299
299
  }
300
300
 
301
301
  bool firstStarted() const {
302
- lock_guard<boost::mutex> l(syncher);
302
+ boost::lock_guard<boost::mutex> l(syncher);
303
303
  return nextCheckupTime == 0;
304
304
  }
305
305
 
@@ -334,12 +334,12 @@ private:
334
334
  scheduleNextCheckup(3 * 60 * 60);
335
335
  }
336
336
 
337
- lock_guard<boost::mutex> l(syncher);
337
+ boost::lock_guard<boost::mutex> l(syncher);
338
338
  this->servers = servers;
339
339
  }
340
340
 
341
341
  void freeThreadData() {
342
- lock_guard<boost::mutex> l(syncher);
342
+ boost::lock_guard<boost::mutex> l(syncher);
343
343
  servers.clear(); // Invoke destructors inside this thread.
344
344
  }
345
345
 
@@ -357,7 +357,7 @@ private:
357
357
  }
358
358
 
359
359
  unsigned int msecUntilNextCheckup() const {
360
- lock_guard<boost::mutex> l(syncher);
360
+ boost::lock_guard<boost::mutex> l(syncher);
361
361
  time_t now = SystemTime::get();
362
362
  if (now >= nextCheckupTime) {
363
363
  return 0;
@@ -367,7 +367,7 @@ private:
367
367
  }
368
368
 
369
369
  bool timeForCheckup() const {
370
- lock_guard<boost::mutex> l(syncher);
370
+ boost::lock_guard<boost::mutex> l(syncher);
371
371
  return SystemTime::get() >= nextCheckupTime;
372
372
  }
373
373
 
@@ -525,7 +525,7 @@ public:
525
525
 
526
526
  if (!queue.tryAdd(item)) {
527
527
  P_WARN("The Union Station gateway isn't responding quickly enough; dropping packet.");
528
- lock_guard<boost::mutex> l(syncher);
528
+ boost::lock_guard<boost::mutex> l(syncher);
529
529
  packetsDropped++;
530
530
  }
531
531
  }
@@ -536,7 +536,7 @@ public:
536
536
 
537
537
  template<typename Stream>
538
538
  void inspect(Stream &stream) const {
539
- lock_guard<boost::mutex> l(syncher);
539
+ boost::lock_guard<boost::mutex> l(syncher);
540
540
  stream << " Available servers (" << servers.size() << "): ";
541
541
  foreach (const ServerPtr server, servers) {
542
542
  stream << server->name() << " ";
@@ -38,7 +38,7 @@ private:
38
38
 
39
39
  while (!this_thread::interruption_requested()) {
40
40
  {
41
- lock_guard<boost::mutex> l(lock);
41
+ boost::lock_guard<boost::mutex> l(lock);
42
42
  pid = this->pid;
43
43
  }
44
44
 
@@ -65,7 +65,7 @@ private:
65
65
  }
66
66
 
67
67
  {
68
- lock_guard<boost::mutex> l(lock);
68
+ boost::lock_guard<boost::mutex> l(lock);
69
69
  this->pid = 0;
70
70
  }
71
71
 
@@ -103,16 +103,16 @@ private:
103
103
  }
104
104
  } catch (const boost::thread_interrupted &) {
105
105
  } catch (const tracable_exception &e) {
106
- lock_guard<boost::mutex> l(lock);
106
+ boost::lock_guard<boost::mutex> l(lock);
107
107
  threadExceptionMessage = e.what();
108
108
  threadExceptionBacktrace = e.backtrace();
109
109
  errorEvent->notify();
110
110
  } catch (const std::exception &e) {
111
- lock_guard<boost::mutex> l(lock);
111
+ boost::lock_guard<boost::mutex> l(lock);
112
112
  threadExceptionMessage = e.what();
113
113
  errorEvent->notify();
114
114
  } catch (...) {
115
- lock_guard<boost::mutex> l(lock);
115
+ boost::lock_guard<boost::mutex> l(lock);
116
116
  threadExceptionMessage = "Unknown error";
117
117
  errorEvent->notify();
118
118
  }
@@ -415,7 +415,7 @@ public:
415
415
  args[0] + "'");
416
416
  }
417
417
 
418
- lock_guard<boost::mutex> l(lock);
418
+ boost::lock_guard<boost::mutex> l(lock);
419
419
  this->feedbackFd = feedbackFd;
420
420
  this->pid = pid;
421
421
  failGuard.clear();
@@ -433,7 +433,7 @@ public:
433
433
  * @throws thread_resource_error
434
434
  */
435
435
  virtual void startWatching() {
436
- lock_guard<boost::mutex> l(lock);
436
+ boost::lock_guard<boost::mutex> l(lock);
437
437
  if (pid == 0) {
438
438
  throw RuntimeException("start() hasn't been called yet");
439
439
  }
@@ -466,7 +466,7 @@ public:
466
466
  * or false if it wasn't started.
467
467
  */
468
468
  virtual bool forceShutdown() {
469
- lock_guard<boost::mutex> l(lock);
469
+ boost::lock_guard<boost::mutex> l(lock);
470
470
  if (pid == 0) {
471
471
  return false;
472
472
  } else {
@@ -482,7 +482,7 @@ public:
482
482
  * everything is still OK.
483
483
  */
484
484
  string getErrorMessage() const {
485
- lock_guard<boost::mutex> l(lock);
485
+ boost::lock_guard<boost::mutex> l(lock);
486
486
  return threadExceptionMessage;
487
487
  }
488
488
 
@@ -490,7 +490,7 @@ public:
490
490
  * The error backtrace, if applicable.
491
491
  */
492
492
  string getErrorBacktrace() const {
493
- lock_guard<boost::mutex> l(lock);
493
+ boost::lock_guard<boost::mutex> l(lock);
494
494
  return threadExceptionBacktrace;
495
495
  }
496
496
 
@@ -500,7 +500,7 @@ public:
500
500
  * has exited without using waitpid().
501
501
  */
502
502
  const FileDescriptor getFeedbackFd() const {
503
- lock_guard<boost::mutex> l(lock);
503
+ boost::lock_guard<boost::mutex> l(lock);
504
504
  return feedbackFd;
505
505
  }
506
506
  };
@@ -44,6 +44,7 @@ protected:
44
44
  VariantMap options = agentsOptions;
45
45
  options.set("logging_agent_address", loggingAgentAddress);
46
46
  options.set("logging_agent_password", loggingAgentPassword);
47
+ options.set("logging_agent_admin_address", loggingAgentAdminAddress);
47
48
  options.writeToFd(fd);
48
49
  }
49
50
 
@@ -63,6 +64,7 @@ public:
63
64
  virtual void reportAgentsInformation(VariantMap &report) {
64
65
  report
65
66
  .set("logging_socket_address", loggingAgentAddress)
66
- .set("logging_socket_password", loggingAgentPassword);
67
+ .set("logging_socket_password", loggingAgentPassword)
68
+ .set("logging_socket_admin_address", loggingAgentAdminAddress);
67
69
  }
68
70
  };
@@ -94,8 +94,13 @@ static ResourceLocator *resourceLocator;
94
94
  static ServerInstanceDirPtr serverInstanceDir;
95
95
  static ServerInstanceDir::GenerationPtr generation;
96
96
  static ServerInstanceDirToucher *serverInstanceDirToucher;
97
+ static uid_t defaultUid;
98
+ static gid_t defaultGid;
97
99
  static string loggingAgentAddress;
98
100
  static string loggingAgentPassword;
101
+ static string loggingAgentAdminAddress;
102
+ static string adminToolStatusPassword;
103
+ static string adminToolManipulationPassword;
99
104
 
100
105
  #include "AgentWatcher.cpp"
101
106
  #include "HelperAgentWatcher.cpp"
@@ -440,6 +445,41 @@ initializeOptions() {
440
445
  P_INFO("Options: " << agentsOptions.inspect());
441
446
  }
442
447
 
448
+ static void
449
+ maybeSetsid() {
450
+ /* Become the session leader so that Apache can't kill the
451
+ * watchdog with killpg() during shutdown, so that a
452
+ * Ctrl-C only affects the web server, and so that
453
+ * we can kill all of our subprocesses in a single killpg().
454
+ *
455
+ * AgentsStarter.h already calls setsid() before exec()ing
456
+ * the Watchdog, but FlyingPassenger does not.
457
+ */
458
+ if (agentsOptions.getBool("setsid", false)) {
459
+ setsid();
460
+ }
461
+ }
462
+
463
+ static void
464
+ lookupDefaultUidGid(uid_t &uid, gid_t &gid) {
465
+ struct passwd *userEntry;
466
+ struct group *groupEntry;
467
+
468
+ userEntry = getpwnam(defaultUser.c_str());
469
+ if (userEntry == NULL) {
470
+ throw NonExistentUserException("Default user '" + defaultUser +
471
+ "' does not exist.");
472
+ }
473
+ uid = userEntry->pw_uid;
474
+
475
+ groupEntry = getgrnam(defaultGroup.c_str());
476
+ if (groupEntry == NULL) {
477
+ throw NonExistentGroupException("Default group '" + defaultGroup +
478
+ "' does not exist.");
479
+ }
480
+ gid = groupEntry->gr_gid;
481
+ }
482
+
443
483
  static void
444
484
  initializeWorkingObjects() {
445
485
  TRACE_POINT();
@@ -474,9 +514,30 @@ initializeWorkingObjects() {
474
514
  UPDATE_TRACE_POINT();
475
515
  serverInstanceDirToucher = new ServerInstanceDirToucher();
476
516
 
517
+ UPDATE_TRACE_POINT();
518
+ lookupDefaultUidGid(defaultUid, defaultGid);
519
+
477
520
  UPDATE_TRACE_POINT();
478
521
  loggingAgentAddress = "unix:" + generation->getPath() + "/logging";
479
522
  loggingAgentPassword = randomGenerator->generateAsciiString(64);
523
+ loggingAgentAdminAddress = "unix:" + generation->getPath() + "/logging_admin";
524
+
525
+ UPDATE_TRACE_POINT();
526
+ adminToolStatusPassword = randomGenerator->generateAsciiString(MESSAGE_SERVER_MAX_PASSWORD_SIZE);
527
+ adminToolManipulationPassword = randomGenerator->generateAsciiString(MESSAGE_SERVER_MAX_PASSWORD_SIZE);
528
+ agentsOptions.set("admin_tool_status_password", adminToolStatusPassword);
529
+ agentsOptions.set("admin_tool_manipulation_password", adminToolManipulationPassword);
530
+ if (geteuid() == 0 && !userSwitching) {
531
+ createFile(generation->getPath() + "/passenger-status-password.txt",
532
+ adminToolStatusPassword, S_IRUSR, defaultUid, defaultGid);
533
+ createFile(generation->getPath() + "/admin-manipulation-password.txt",
534
+ adminToolManipulationPassword, S_IRUSR, defaultUid, defaultGid);
535
+ } else {
536
+ createFile(generation->getPath() + "/passenger-status-password.txt",
537
+ adminToolStatusPassword, S_IRUSR | S_IWUSR);
538
+ createFile(generation->getPath() + "/admin-manipulation-password.txt",
539
+ adminToolManipulationPassword, S_IRUSR | S_IWUSR);
540
+ }
480
541
  }
481
542
 
482
543
  static void
@@ -545,6 +606,7 @@ main(int argc, char *argv[]) {
545
606
  try {
546
607
  TRACE_POINT();
547
608
  initializeOptions();
609
+ maybeSetsid();
548
610
  initializeWorkingObjects();
549
611
  initializeAgentWatchers();
550
612
  } catch (const std::exception &e) {