passenger 5.3.4 → 5.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +13 -0
  3. data/CODE_OF_CONDUCT.md +1 -1
  4. data/build/cxx_tests.rb +12 -1
  5. data/build/misc.rb +2 -1
  6. data/build/packaging.rb +2 -0
  7. data/build/support/cplusplus.rb +2 -2
  8. data/build/support/cxx_dependency_map.rb +653 -383
  9. data/dev/configkit-schemas/index.json +105 -3
  10. data/dev/show-latest-crashlog-dir +27 -0
  11. data/resources/templates/standalone/http.erb +2 -0
  12. data/src/agent/Core/AdminPanelConnector.h +2 -2
  13. data/src/agent/Core/ApplicationPool/Context.h +5 -1
  14. data/src/agent/Core/ApplicationPool/Group.h +2 -0
  15. data/src/agent/Core/ApplicationPool/Group/LifetimeAndBasics.cpp +5 -0
  16. data/src/agent/Core/ApplicationPool/Group/Miscellaneous.cpp +2 -1
  17. data/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +1 -1
  18. data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +12 -19
  19. data/src/agent/Core/ApplicationPool/Options.h +35 -31
  20. data/src/agent/Core/ApplicationPool/Pool/GroupUtils.cpp +2 -1
  21. data/src/agent/Core/ApplicationPool/Socket.h +1 -1
  22. data/src/agent/Core/Config.h +38 -7
  23. data/src/agent/Core/ConfigChange.cpp +13 -1
  24. data/src/agent/Core/Controller.h +3 -1
  25. data/src/agent/Core/Controller/Config.h +14 -11
  26. data/src/agent/Core/Controller/InitRequest.cpp +6 -5
  27. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +3 -0
  28. data/src/agent/Core/CoreMain.cpp +149 -34
  29. data/src/agent/Core/OptionParser.h +12 -1
  30. data/src/agent/Core/SpawningKit/Config.h +1 -1
  31. data/src/agent/Core/SpawningKit/Context.h +7 -1
  32. data/src/agent/Core/SpawningKit/Exceptions.h +15 -12
  33. data/src/agent/Core/SpawningKit/README.md +34 -17
  34. data/src/agent/Core/SpawningKit/Spawner.h +5 -3
  35. data/src/agent/Core/SpawningKit/UserSwitchingRules.h +5 -2
  36. data/src/agent/Core/TelemetryCollector.h +674 -0
  37. data/src/agent/Shared/Fundamentals/AbortHandler.cpp +309 -83
  38. data/src/agent/Shared/Fundamentals/AbortHandler.h +18 -3
  39. data/src/agent/Watchdog/Config.h +21 -4
  40. data/src/agent/Watchdog/WatchdogMain.cpp +4 -1
  41. data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +10 -0
  42. data/src/apache2_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.cpp +5 -0
  43. data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +30 -0
  44. data/src/apache2_module/DirectoryMapper.h +24 -36
  45. data/src/apache2_module/Hooks.cpp +13 -5
  46. data/src/apache2_module/ServerConfig/AutoGeneratedManifestGeneration.cpp +20 -0
  47. data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h +24 -0
  48. data/src/cxx_supportlib/AppTypeDetector/CBindings.cpp +136 -0
  49. data/src/cxx_supportlib/AppTypeDetector/CBindings.h +73 -0
  50. data/src/cxx_supportlib/{AppTypes.h → AppTypeDetector/Detector.h} +59 -132
  51. data/src/cxx_supportlib/ConfigKit/README.md +90 -2
  52. data/src/cxx_supportlib/ConfigKit/Schema.h +58 -13
  53. data/src/cxx_supportlib/ConfigKit/Store.h +128 -4
  54. data/src/cxx_supportlib/Constants.h +1 -1
  55. data/src/cxx_supportlib/ProcessManagement/Ruby.cpp +3 -3
  56. data/src/cxx_supportlib/ProcessManagement/Ruby.h +7 -2
  57. data/src/cxx_supportlib/ProcessManagement/Spawn.cpp +14 -7
  58. data/src/cxx_supportlib/ProcessManagement/Spawn.h +21 -2
  59. data/src/cxx_supportlib/ResourceLocator.h +1 -1
  60. data/src/cxx_supportlib/ServerKit/ClientRef.h +17 -7
  61. data/src/cxx_supportlib/ServerKit/HttpRequestRef.h +17 -7
  62. data/src/cxx_supportlib/Utils/IOUtils.cpp +2 -1
  63. data/src/cxx_supportlib/Utils/ProcessMetricsCollector.h +9 -6
  64. data/src/cxx_supportlib/WrapperRegistry/CBindings.cpp +85 -0
  65. data/src/cxx_supportlib/WrapperRegistry/CBindings.h +56 -0
  66. data/src/cxx_supportlib/WrapperRegistry/Entry.h +112 -0
  67. data/src/cxx_supportlib/WrapperRegistry/README.md +37 -0
  68. data/src/cxx_supportlib/WrapperRegistry/Registry.h +309 -0
  69. data/src/helper-scripts/download_binaries/extconf.rb +6 -2
  70. data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +16 -0
  71. data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c +6 -0
  72. data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +24 -0
  73. data/src/nginx_module/ContentHandler.c +34 -13
  74. data/src/nginx_module/ContentHandler.h +3 -3
  75. data/src/nginx_module/MainConfig/AutoGeneratedCreateFunction.c +11 -0
  76. data/src/nginx_module/MainConfig/AutoGeneratedManifestGeneration.c +23 -0
  77. data/src/nginx_module/MainConfig/AutoGeneratedStruct.h +8 -0
  78. data/src/nginx_module/config +2 -1
  79. data/src/nginx_module/ngx_http_passenger_module.c +9 -3
  80. data/src/nginx_module/ngx_http_passenger_module.h +4 -2
  81. data/src/ruby_supportlib/phusion_passenger.rb +2 -1
  82. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +13 -0
  83. data/src/ruby_supportlib/phusion_passenger/common_library.rb +8 -5
  84. data/src/ruby_supportlib/phusion_passenger/config/download_agent_command.rb +6 -2
  85. data/src/ruby_supportlib/phusion_passenger/config/download_nginx_engine_command.rb +6 -2
  86. data/src/ruby_supportlib/phusion_passenger/native_support.rb +7 -3
  87. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +15 -0
  88. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +11 -1
  89. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +3 -1
  90. metadata +12 -4
  91. data/src/cxx_supportlib/AppTypes.cpp +0 -109
@@ -253,7 +253,7 @@ public:
253
253
  }
254
254
 
255
255
  bool isTotallyBusy() const {
256
- return concurrency != 0 && sessions >= concurrency;
256
+ return concurrency > 0 && sessions >= concurrency;
257
257
  }
258
258
 
259
259
  void recreateStrings(psg_pool_t *newPool) {
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2017 Phusion Holding B.V.
3
+ * Copyright (c) 2011-2018 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -41,8 +41,10 @@
41
41
  #include <ConfigKit/PrefixTranslator.h>
42
42
  #include <ServerKit/Context.h>
43
43
  #include <ServerKit/HttpServer.h>
44
+ #include <WrapperRegistry/Registry.h>
44
45
  #include <Core/Controller/Config.h>
45
46
  #include <Core/SecurityUpdateChecker.h>
47
+ #include <Core/TelemetryCollector.h>
46
48
  #include <Core/ApiServer.h>
47
49
  #include <Core/AdminPanelConnector.h>
48
50
  #include <Shared/ApiAccountUtils.h>
@@ -154,13 +156,24 @@ using namespace std;
154
156
  * security_update_checker_interval unsigned integer - default(86400)
155
157
  * security_update_checker_proxy_url string - -
156
158
  * security_update_checker_url string - default("https://securitycheck.phusionpassenger.com/v1/check.json")
157
- * server_software string - default("Phusion_Passenger/5.3.4")
159
+ * server_software string - default("Phusion_Passenger/5.3.5")
158
160
  * show_version_in_header boolean - default(true)
159
161
  * single_app_mode_app_root string - default,read_only
160
162
  * single_app_mode_app_type string - read_only
161
163
  * single_app_mode_startup_file string - read_only
162
164
  * standalone_engine string - default
163
165
  * stat_throttle_rate unsigned integer - default(10)
166
+ * telemetry_collector_ca_certificate_path string - -
167
+ * telemetry_collector_debug_curl boolean - default(false)
168
+ * telemetry_collector_disabled boolean - default(false)
169
+ * telemetry_collector_final_run_timeout unsigned integer - default(5)
170
+ * telemetry_collector_first_interval unsigned integer - default(7200)
171
+ * telemetry_collector_interval unsigned integer - default(21600)
172
+ * telemetry_collector_interval_jitter unsigned integer - default(7200)
173
+ * telemetry_collector_proxy_url string - -
174
+ * telemetry_collector_timeout unsigned integer - default(180)
175
+ * telemetry_collector_url string - default("https://anontelemetry.phusionpassenger.com/v1/collect.json")
176
+ * telemetry_collector_verify_server boolean - default(true)
164
177
  * turbocaching boolean - default(true),read_only
165
178
  * user_switching boolean - default(true)
166
179
  * vary_turbocache_by_cookie string - -
@@ -241,7 +254,9 @@ private:
241
254
  }
242
255
  }
243
256
 
244
- static void validateSingleAppMode(const ConfigKit::Store &config, vector<ConfigKit::Error> &errors) {
257
+ static void validateSingleAppMode(const ConfigKit::Store &config,
258
+ const WrapperRegistry::Registry *wrapperRegistry, vector<ConfigKit::Error> &errors)
259
+ {
245
260
  typedef ConfigKit::Error Error;
246
261
 
247
262
  if (config["multi_app"].asBool()) {
@@ -251,7 +266,8 @@ private:
251
266
  // single_app_mode_app_type and single_app_mode_startup_file are
252
267
  // autodetected in initializeSingleAppMode()
253
268
 
254
- ControllerSingleAppModeSchema::validateAppType("single_app_mode_app_type", config, errors);
269
+ ControllerSingleAppModeSchema::validateAppType("single_app_mode_app_type",
270
+ wrapperRegistry, config, errors);
255
271
  }
256
272
 
257
273
  static void validateControllerSecureHeadersPassword(const ConfigKit::Store &config, vector<ConfigKit::Error> &errors) {
@@ -348,9 +364,13 @@ public:
348
364
  ControllerSchema schema;
349
365
  ConfigKit::TableTranslator translator;
350
366
  } controller;
351
- struct {
367
+ struct ControllerSingleAppModeSubschemaContainer {
352
368
  ControllerSingleAppModeSchema schema;
353
369
  ConfigKit::PrefixTranslator translator;
370
+
371
+ ControllerSingleAppModeSubschemaContainer(const WrapperRegistry::Registry *registry)
372
+ : schema(registry)
373
+ { }
354
374
  } controllerSingleAppMode;
355
375
  struct {
356
376
  ServerKit::Schema schema;
@@ -360,6 +380,10 @@ public:
360
380
  SecurityUpdateChecker::Schema schema;
361
381
  ConfigKit::PrefixTranslator translator;
362
382
  } securityUpdateChecker;
383
+ struct {
384
+ TelemetryCollector::Schema schema;
385
+ ConfigKit::PrefixTranslator translator;
386
+ } telemetryCollector;
363
387
  struct {
364
388
  ApiServer::Schema schema;
365
389
  ConfigKit::TableTranslator translator;
@@ -373,7 +397,9 @@ public:
373
397
  ConfigKit::TableTranslator translator;
374
398
  } adminPanelConnector;
375
399
 
376
- Schema() {
400
+ Schema(const WrapperRegistry::Registry *wrapperRegistry = NULL)
401
+ : controllerSingleAppMode(wrapperRegistry)
402
+ {
377
403
  using namespace ConfigKit;
378
404
 
379
405
  // Add subschema: loggingKit
@@ -410,6 +436,10 @@ public:
410
436
  erase("security_update_checker_server_identifier");
411
437
  erase("security_update_checker_web_server_version");
412
438
 
439
+ // Add subschema: telemetryCollector
440
+ telemetryCollector.translator.setPrefixAndFinalize("telemetry_collector_");
441
+ addSubSchema(telemetryCollector.schema, telemetryCollector.translator);
442
+
413
443
  // Add subschema: apiServer
414
444
  apiServer.translator.add("api_server_authorizations", "authorizations");
415
445
  addSubSchemaPrefixTranslations<ServerKit::HttpServerSchema>(
@@ -453,7 +483,8 @@ public:
453
483
  add("file_descriptor_ulimit", UINT_TYPE, OPTIONAL | READ_ONLY, 0);
454
484
 
455
485
  addValidator(validateMultiAppMode);
456
- addValidator(validateSingleAppMode);
486
+ addValidator(boost::bind(validateSingleAppMode, boost::placeholders::_1,
487
+ wrapperRegistry, boost::placeholders::_2));
457
488
  addValidator(validateControllerSecureHeadersPassword);
458
489
  addValidator(validateApplicationPool);
459
490
  addValidator(validateController);
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2017 Phusion Holding B.V.
3
+ * Copyright (c) 2011-2018 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -49,6 +49,7 @@ struct ConfigChangeRequest {
49
49
  boost::scoped_ptr<ConfigKit::Store> config;
50
50
  LoggingKit::ConfigChangeRequest forLoggingKit;
51
51
  SecurityUpdateChecker::ConfigChangeRequest forSecurityUpdateChecker;
52
+ TelemetryCollector::ConfigChangeRequest forTelemetryCollector;
52
53
  vector<ServerKit::ConfigChangeRequest *> forControllerServerKit;
53
54
  vector<Controller::ConfigChangeRequest *> forController;
54
55
  ServerKit::ConfigChangeRequest forApiServerKit;
@@ -188,6 +189,13 @@ asyncPrepareConfigChange(const Json::Value &updates, ConfigChangeRequest *req,
188
189
  coreSchema->securityUpdateChecker.translator,
189
190
  req->config->inspectEffectiveValues(),
190
191
  req->errors, req->forSecurityUpdateChecker);
192
+ if (workingObjects->telemetryCollector != NULL) {
193
+ ConfigKit::prepareConfigChangeForSubComponent(
194
+ *workingObjects->telemetryCollector,
195
+ coreSchema->telemetryCollector.translator,
196
+ req->config->inspectEffectiveValues(),
197
+ req->errors, req->forTelemetryCollector);
198
+ }
191
199
 
192
200
  req->forControllerServerKit.resize(wo->threadWorkingObjects.size(), NULL);
193
201
  req->forController.resize(wo->threadWorkingObjects.size(), NULL);
@@ -287,6 +295,10 @@ asyncCommitConfigChange(ConfigChangeRequest *req, const CommitConfigChangeCallba
287
295
  LoggingKit::context->commitConfigChange(req->forLoggingKit);
288
296
  workingObjects->securityUpdateChecker->commitConfigChange(
289
297
  req->forSecurityUpdateChecker);
298
+ if (workingObjects->telemetryCollector != NULL) {
299
+ workingObjects->telemetryCollector->commitConfigChange(
300
+ req->forTelemetryCollector);
301
+ }
290
302
 
291
303
  wo->appPool->setMax(coreConfig->get("max_pool_size").asInt());
292
304
  wo->appPool->setMaxIdleTime(coreConfig->get("pool_idle_time").asInt() * 1000000ULL);
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2017 Phusion Holding B.V.
3
+ * Copyright (c) 2011-2018 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -71,6 +71,7 @@
71
71
  #include <MemoryKit/palloc.h>
72
72
  #include <DataStructures/LString.h>
73
73
  #include <DataStructures/StringKeyTable.h>
74
+ #include <WrapperRegistry/Registry.h>
74
75
  #include <StaticString.h>
75
76
  #include <Utils.h>
76
77
  #include <Utils/StrIntUtils.h>
@@ -365,6 +366,7 @@ public:
365
366
 
366
367
  // Dependencies
367
368
  ResourceLocator *resourceLocator;
369
+ WrapperRegistry::Registry *wrapperRegistry;
368
370
  PoolPtr appPool;
369
371
 
370
372
 
@@ -39,7 +39,7 @@
39
39
  #include <MemoryKit/palloc.h>
40
40
  #include <ServerKit/HttpServer.h>
41
41
  #include <SystemTools/UserDatabase.h>
42
- #include <AppTypes.h>
42
+ #include <WrapperRegistry/Registry.h>
43
43
  #include <Constants.h>
44
44
  #include <Exceptions.h>
45
45
  #include <StaticString.h>
@@ -113,7 +113,7 @@ parseControllerBenchmarkMode(const StaticString &mode) {
113
113
  * multi_app boolean - default(true),read_only
114
114
  * request_freelist_limit unsigned integer - default(1024)
115
115
  * response_buffer_high_watermark unsigned integer - default(134217728)
116
- * server_software string - default("Phusion_Passenger/5.3.4")
116
+ * server_software string - default("Phusion_Passenger/5.3.5")
117
117
  * show_version_in_header boolean - default(true)
118
118
  * start_reading_after_accept boolean - default(true)
119
119
  * stat_throttle_rate unsigned integer - default(10)
@@ -230,7 +230,7 @@ public:
230
230
  * END
231
231
  */
232
232
  struct ControllerSingleAppModeSchema: public ConfigKit::Schema {
233
- ControllerSingleAppModeSchema() {
233
+ ControllerSingleAppModeSchema(const WrapperRegistry::Registry *wrapperRegistry = NULL) {
234
234
  using namespace ConfigKit;
235
235
 
236
236
  addWithDynamicDefault("app_root", STRING_TYPE, OPTIONAL | READ_ONLY | CACHE_DEFAULT_VALUE,
@@ -238,7 +238,7 @@ struct ControllerSingleAppModeSchema: public ConfigKit::Schema {
238
238
  add("app_type", STRING_TYPE, REQUIRED | READ_ONLY);
239
239
  add("startup_file", STRING_TYPE, REQUIRED | READ_ONLY);
240
240
 
241
- addValidator(boost::bind(validateAppType, "app_type",
241
+ addValidator(boost::bind(validateAppType, "app_type", wrapperRegistry,
242
242
  boost::placeholders::_1, boost::placeholders::_2));
243
243
  addNormalizer(normalizeAppRoot);
244
244
  addNormalizer(normalizeStartupFile);
@@ -258,21 +258,24 @@ struct ControllerSingleAppModeSchema: public ConfigKit::Schema {
258
258
  }
259
259
 
260
260
  static void validateAppType(const string &appTypeKey,
261
+ const WrapperRegistry::Registry *wrapperRegistry,
261
262
  const ConfigKit::Store &config, vector<ConfigKit::Error> &errors)
262
263
  {
263
264
  typedef ConfigKit::Error Error;
264
265
 
265
- if (!config[appTypeKey].isNull()) {
266
- PassengerAppType appType = getAppType(config[appTypeKey].asString());
267
- if (appType == PAT_NONE || appType == PAT_ERROR) {
266
+ if (!config[appTypeKey].isNull() && wrapperRegistry != NULL) {
267
+ const WrapperRegistry::Entry &entry =
268
+ wrapperRegistry->lookup(config[appTypeKey].asString());
269
+ if (entry.isNull()) {
268
270
  string message = "'{{" + appTypeKey + "}}' is set to '"
269
271
  + config[appTypeKey].asString() + "', which is not a"
270
272
  " valid application type. Supported app types are:";
271
- const AppTypeDefinition *definition = &appTypeDefinitions[0];
272
- while (definition->type != PAT_NONE) {
273
+ WrapperRegistry::Registry::ConstIterator it(
274
+ wrapperRegistry->getIterator());
275
+ while (*it != NULL) {
273
276
  message.append(1, ' ');
274
- message.append(definition->name);
275
- definition++;
277
+ message.append(it.getValue().language);
278
+ it.next();
276
279
  }
277
280
  errors.push_back(Error(message));
278
281
  }
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2017 Phusion Holding B.V.
3
+ * Copyright (c) 2011-2018 Phusion Holding B.V.
4
4
  *
5
5
  * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
6
  * trademarks of Phusion Holding B.V.
@@ -24,6 +24,7 @@
24
24
  * THE SOFTWARE.
25
25
  */
26
26
  #include <Core/Controller.h>
27
+ #include <AppTypeDetector/Detector.h>
27
28
 
28
29
  /*************************************************************************
29
30
  *
@@ -336,13 +337,13 @@ Controller::createNewPoolOptions(Client *client, Request *req,
336
337
 
337
338
  const LString *appType = secureHeaders.lookup("!~PASSENGER_APP_TYPE");
338
339
  if (appType == NULL || appType->size == 0) {
339
- AppTypeDetector detector;
340
- PassengerAppType type = detector.checkAppRoot(options.appRoot);
341
- if (type == PAT_NONE || type == PAT_ERROR) {
340
+ AppTypeDetector::Detector detector(*wrapperRegistry);
341
+ AppTypeDetector::Detector::Result result = detector.checkAppRoot(options.appRoot);
342
+ if (result.isNull()) {
342
343
  disconnectWithError(&client, "client did not send a recognized !~PASSENGER_APP_TYPE header");
343
344
  return;
344
345
  }
345
- options.appType = getAppTypeName(type);
346
+ options.appType = result.wrapperRegistryEntry->language;
346
347
  } else {
347
348
  fillPoolOption(req, options.appType, "!~PASSENGER_APP_TYPE");
348
349
  }
@@ -94,6 +94,9 @@ Controller::initialize() {
94
94
  if (resourceLocator == NULL) {
95
95
  throw RuntimeException("ResourceLocator not initialized");
96
96
  }
97
+ if (wrapperRegistry == NULL) {
98
+ throw RuntimeException("WrapperRegistry not initialized");
99
+ }
97
100
  if (appPool == NULL) {
98
101
  throw RuntimeException("AppPool not initialized");
99
102
  }
@@ -81,6 +81,7 @@
81
81
  #include <ConfigKit/SubComponentUtils.h>
82
82
  #include <ServerKit/Server.h>
83
83
  #include <ServerKit/AcceptLoadBalancer.h>
84
+ #include <AppTypeDetector/Detector.h>
84
85
  #include <MessageReadersWriters.h>
85
86
  #include <FileDescriptor.h>
86
87
  #include <ResourceLocator.h>
@@ -98,6 +99,7 @@
98
99
  #include <Core/ConfigChange.h>
99
100
  #include <Core/ApplicationPool/Pool.h>
100
101
  #include <Core/SecurityUpdateChecker.h>
102
+ #include <Core/TelemetryCollector.h>
101
103
  #include <Core/AdminPanelConnector.h>
102
104
 
103
105
  using namespace boost;
@@ -165,6 +167,7 @@ namespace Core {
165
167
  oxt::thread *prestarterThread;
166
168
 
167
169
  SecurityUpdateChecker *securityUpdateChecker;
170
+ TelemetryCollector *telemetryCollector;
168
171
  AdminPanelConnector *adminPanelConnector;
169
172
  oxt::thread *adminPanelConnectorThread;
170
173
 
@@ -175,6 +178,7 @@ namespace Core {
175
178
  shutdownCounter(0),
176
179
  prestarterThread(NULL),
177
180
  securityUpdateChecker(NULL),
181
+ telemetryCollector(NULL),
178
182
  adminPanelConnector(NULL),
179
183
  adminPanelConnectorThread(NULL)
180
184
  /*******************/
@@ -190,6 +194,7 @@ namespace Core {
190
194
  delete adminPanelConnectorThread;
191
195
  delete adminPanelConnector;
192
196
  delete securityUpdateChecker;
197
+ delete telemetryCollector;
193
198
 
194
199
  /*******************/
195
200
  /*******************/
@@ -211,6 +216,7 @@ namespace Core {
211
216
 
212
217
  using namespace Passenger::Core;
213
218
 
219
+ static WrapperRegistry::Registry *coreWrapperRegistry;
214
220
  static Schema *coreSchema;
215
221
  static ConfigKit::Store *coreConfig;
216
222
  static WorkingObjects *workingObjects;
@@ -257,9 +263,9 @@ initializeSingleAppMode() {
257
263
 
258
264
  if (coreConfig->get("single_app_mode_app_type").isNull()) {
259
265
  P_DEBUG("Autodetecting application type...");
260
- AppTypeDetector detector(NULL, 0);
261
- PassengerAppType appTypeEnum = detector.checkAppRoot(appRoot);
262
- if (appTypeEnum == PAT_NONE || appTypeEnum == PAT_ERROR) {
266
+ AppTypeDetector::Detector detector(*coreWrapperRegistry, NULL, 0);
267
+ AppTypeDetector::Detector::Result result = detector.checkAppRoot(appRoot);
268
+ if (result.isNull()) {
263
269
  fprintf(stderr, "ERROR: unable to autodetect what kind of application "
264
270
  "lives in %s. Please specify information about the app using "
265
271
  "--app-type and --startup-file, or specify a correct location to "
@@ -269,13 +275,18 @@ initializeSingleAppMode() {
269
275
  exit(1);
270
276
  }
271
277
 
272
- appType = getAppTypeName(appTypeEnum);
278
+ appType = result.wrapperRegistryEntry->language;
273
279
  } else {
274
280
  appType = coreConfig->get("single_app_mode_app_type").asString();
275
281
  }
276
282
 
277
283
  if (coreConfig->get("single_app_mode_startup_file").isNull()) {
278
- startupFile = appRoot + "/" + getAppTypeStartupFile(getAppType(appType));
284
+ const WrapperRegistry::Entry &entry = coreWrapperRegistry->lookup(appType);
285
+ if (entry.defaultStartupFiles.empty()) {
286
+ startupFile = appRoot + "/";
287
+ } else {
288
+ startupFile = appRoot + "/" + entry.defaultStartupFiles[0];
289
+ }
279
290
  } else {
280
291
  startupFile = coreConfig->get("single_app_mode_startup_file").asString();
281
292
  }
@@ -551,39 +562,62 @@ printInfoInThread() {
551
562
  }
552
563
 
553
564
  static void
554
- dumpDiagnosticsOnCrash(void *userData) {
555
- WorkingObjects *wo = workingObjects;
556
- unsigned int i;
557
-
558
- cerr << "### Backtraces\n";
565
+ dumpOxtBacktracesOnCrash(void *userData) {
559
566
  cerr << oxt::thread::all_backtraces();
560
567
  cerr.flush();
568
+ }
569
+
570
+ static void
571
+ dumpControllerStatesOnCrash(void *userData) {
572
+ WorkingObjects *wo = workingObjects;
573
+ unsigned int i;
561
574
 
562
575
  for (i = 0; i < wo->threadWorkingObjects.size(); i++) {
563
576
  ThreadWorkingObjects *two = &wo->threadWorkingObjects[i];
564
- cerr << "### Request handler state (thread " << (i + 1) << ")\n";
577
+ cerr << "####### Controller state (thread " << (i + 1) << ") #######\n";
565
578
  cerr << two->controller->inspectStateAsJson();
566
- cerr << "\n";
579
+ cerr << "\n\n";
567
580
  cerr.flush();
568
581
  }
582
+ }
583
+
584
+ static void
585
+ dumpControllerConfigsOnCrash(void *userData) {
586
+ WorkingObjects *wo = workingObjects;
587
+ unsigned int i;
569
588
 
570
589
  for (i = 0; i < wo->threadWorkingObjects.size(); i++) {
571
590
  ThreadWorkingObjects *two = &wo->threadWorkingObjects[i];
572
- cerr << "### Request handler config (thread " << (i + 1) << ")\n";
591
+ cerr << "####### Controller config (thread " << (i + 1) << ") #######\n";
573
592
  cerr << two->controller->inspectConfig();
574
- cerr << "\n";
593
+ cerr << "\n\n";
575
594
  cerr.flush();
576
595
  }
596
+ }
597
+
598
+ static void
599
+ dumpPoolStateOnCrash(void *userData) {
600
+ WorkingObjects *wo = workingObjects;
577
601
 
578
- cerr << "### Pool state (simple)\n";
602
+ cerr << "####### Pool state (simple) #######\n";
579
603
  // Do not lock, the crash may occur within the pool.
580
604
  Pool::InspectOptions options(Pool::InspectOptions::makeAuthorized());
581
605
  options.verbose = true;
582
606
  cerr << wo->appPool->inspect(options, false);
583
- cerr << "\n";
607
+ cerr << "\n\n";
584
608
  cerr.flush();
585
609
 
586
- cerr << "### mbuf stats\n\n";
610
+ cerr << "####### Pool state (XML) #######\n";
611
+ Pool::ToXmlOptions options2(Pool::ToXmlOptions::makeAuthorized());
612
+ options2.secrets = true;
613
+ cerr << wo->appPool->toXml(options2, false);
614
+ cerr << "\n\n";
615
+ cerr.flush();
616
+ }
617
+
618
+ static void
619
+ dumpMbufStatsOnCrash(void *userData) {
620
+ WorkingObjects *wo = workingObjects;
587
621
  cerr << "nfree_mbuf_blockq : " <<
588
622
  wo->threadWorkingObjects[0].serverKitContext->mbuf_pool.nfree_mbuf_blockq << "\n";
589
623
  cerr << "nactive_mbuf_blockq: " <<
@@ -592,13 +626,6 @@ dumpDiagnosticsOnCrash(void *userData) {
592
626
  wo->threadWorkingObjects[0].serverKitContext->mbuf_pool.mbuf_block_chunk_size << "\n";
593
627
  cerr << "\n";
594
628
  cerr.flush();
595
-
596
- cerr << "### Pool state (XML)\n";
597
- Pool::ToXmlOptions options2(Pool::ToXmlOptions::makeAuthorized());
598
- options2.secrets = true;
599
- cerr << wo->appPool->toXml(options2, false);
600
- cerr << "\n\n";
601
- cerr.flush();
602
629
  }
603
630
 
604
631
  static void
@@ -653,6 +680,7 @@ initializeNonPrivilegedWorkingObjects() {
653
680
  wo->spawningKitContext = boost::make_shared<SpawningKit::Context>(
654
681
  wo->spawningKitContextSchema);
655
682
  wo->spawningKitContext->resourceLocator = &wo->resourceLocator;
683
+ wo->spawningKitContext->wrapperRegistry = coreWrapperRegistry;
656
684
  wo->spawningKitContext->randomGenerator = wo->randomGenerator;
657
685
  wo->spawningKitContext->integrationMode = coreConfig->get("integration_mode").asString();
658
686
  wo->spawningKitContext->instanceDir = coreConfig->get("instance_dir").asString();
@@ -713,6 +741,7 @@ initializeNonPrivilegedWorkingObjects() {
713
741
  &wo->singleAppModeConfig,
714
742
  coreSchema->controllerSingleAppMode.translator);
715
743
  two.controller->resourceLocator = &wo->resourceLocator;
744
+ two.controller->wrapperRegistry = coreWrapperRegistry;
716
745
  two.controller->appPool = wo->appPool;
717
746
  two.controller->shutdownFinishCallback = controllerShutdownFinished;
718
747
  two.controller->initialize();
@@ -821,6 +850,27 @@ initializeSecurityUpdateChecker() {
821
850
  checker->start();
822
851
  }
823
852
 
853
+ static void
854
+ initializeTelemetryCollector() {
855
+ return; // disable for now
856
+ TRACE_POINT();
857
+ WorkingObjects &wo = *workingObjects;
858
+
859
+ Json::Value config = coreConfig->inspectEffectiveValues();
860
+ TelemetryCollector *collector = new TelemetryCollector(
861
+ coreSchema->telemetryCollector.schema,
862
+ coreConfig->inspectEffectiveValues(),
863
+ coreSchema->telemetryCollector.translator);
864
+ wo.telemetryCollector = collector;
865
+ for (unsigned int i = 0; i < wo.threadWorkingObjects.size(); i++) {
866
+ ThreadWorkingObjects *two = &wo.threadWorkingObjects[i];
867
+ collector->controllers.push_back(two->controller);
868
+ }
869
+ collector->initialize();
870
+ collector->start();
871
+ wo.shutdownCounter.fetch_add(1, boost::memory_order_relaxed);
872
+ }
873
+
824
874
  static void
825
875
  runAdminPanelConnector(AdminPanelConnector *connector) {
826
876
  connector->run();
@@ -968,6 +1018,50 @@ reportInitializationInfo() {
968
1018
  }
969
1019
  }
970
1020
 
1021
+ static void
1022
+ initializeAbortHandlerCustomerDiagnostics() {
1023
+ if (!Agent::Fundamentals::abortHandlerInstalled()) {
1024
+ return;
1025
+ }
1026
+
1027
+ Agent::Fundamentals::AbortHandlerConfig::DiagnosticsDumper *diagnosticsDumpers
1028
+ = &Agent::Fundamentals::context->abortHandlerConfig.diagnosticsDumpers[0];
1029
+
1030
+ diagnosticsDumpers[0].name = "OXT backtraces";
1031
+ diagnosticsDumpers[0].logFileName = "backtrace_oxt.log";
1032
+ diagnosticsDumpers[0].func = dumpOxtBacktracesOnCrash;
1033
+
1034
+ diagnosticsDumpers[1].name = "controller states";
1035
+ diagnosticsDumpers[1].logFileName = "controller_states.log";
1036
+ diagnosticsDumpers[1].func = dumpControllerStatesOnCrash;
1037
+
1038
+ diagnosticsDumpers[2].name = "controller configs";
1039
+ diagnosticsDumpers[2].logFileName = "controller_configs.log";
1040
+ diagnosticsDumpers[2].func = dumpControllerConfigsOnCrash;
1041
+
1042
+ diagnosticsDumpers[3].name = "pool state";
1043
+ diagnosticsDumpers[3].logFileName = "pool.log";
1044
+ diagnosticsDumpers[3].func = dumpPoolStateOnCrash;
1045
+
1046
+ diagnosticsDumpers[4].name = "mbuf statistics";
1047
+ diagnosticsDumpers[4].logFileName = "mbufs.log";
1048
+ diagnosticsDumpers[4].func = dumpMbufStatsOnCrash;
1049
+
1050
+ Agent::Fundamentals::abortHandlerConfigChanged();
1051
+ }
1052
+
1053
+ static void
1054
+ uninstallAbortHandlerCustomDiagnostics() {
1055
+ if (!Agent::Fundamentals::abortHandlerInstalled()) {
1056
+ return;
1057
+ }
1058
+
1059
+ for (unsigned int i = 0; i < Agent::Fundamentals::AbortHandlerConfig::MAX_DIAGNOSTICS_DUMPERS; i++) {
1060
+ Agent::Fundamentals::context->abortHandlerConfig.diagnosticsDumpers[i].func = NULL;
1061
+ }
1062
+ Agent::Fundamentals::abortHandlerConfigChanged();
1063
+ }
1064
+
971
1065
  static void
972
1066
  mainLoop() {
973
1067
  TRACE_POINT();
@@ -978,9 +1072,6 @@ mainLoop() {
978
1072
  && maxCpus <= CPU_SETSIZE;
979
1073
  #endif
980
1074
 
981
- Agent::Fundamentals::context->abortHandlerConfig.diagnosticsDumper = dumpDiagnosticsOnCrash;
982
- Agent::Fundamentals::abortHandlerConfigChanged();
983
-
984
1075
  for (unsigned int i = 0; i < wo->threadWorkingObjects.size(); i++) {
985
1076
  ThreadWorkingObjects *two = &wo->threadWorkingObjects[i];
986
1077
  two->bgloop->start("Main event loop: thread " + toString(i + 1), 0);
@@ -1064,6 +1155,20 @@ apiServerShutdownFinished(Core::ApiServer::ApiServer *server) {
1064
1155
  serverShutdownFinished();
1065
1156
  }
1066
1157
 
1158
+ static void
1159
+ telemetryCollectorAsyncShutdownThreadMain() {
1160
+ WorkingObjects *wo = workingObjects;
1161
+ wo->telemetryCollector->stop();
1162
+ serverShutdownFinished();
1163
+ }
1164
+
1165
+ static void
1166
+ asyncShutdownTelemetryCollector() {
1167
+ oxt::thread(telemetryCollectorAsyncShutdownThreadMain,
1168
+ "Telemetry collector shutdown",
1169
+ 512 * 1024);
1170
+ }
1171
+
1067
1172
  /* Wait until the watchdog closes the feedback fd (meaning it
1068
1173
  * was killed) or until we receive an exit message.
1069
1174
  */
@@ -1085,8 +1190,7 @@ waitForExitEvent() {
1085
1190
  TRACE_POINT();
1086
1191
  if (syscalls::select(largestFd + 1, &fds, NULL, NULL, NULL) == -1) {
1087
1192
  int e = errno;
1088
- Agent::Fundamentals::context->abortHandlerConfig.diagnosticsDumper = NULL;
1089
- Agent::Fundamentals::abortHandlerConfigChanged();
1193
+ uninstallAbortHandlerCustomDiagnostics();
1090
1194
  throw SystemException("select() failed", e);
1091
1195
  }
1092
1196
 
@@ -1122,6 +1226,9 @@ waitForExitEvent() {
1122
1226
  if (wo->apiWorkingObjects.apiServer != NULL) {
1123
1227
  wo->apiWorkingObjects.bgloop->safe->runLater(shutdownApiServer);
1124
1228
  }
1229
+ if (wo->telemetryCollector != NULL) {
1230
+ asyncShutdownTelemetryCollector();
1231
+ }
1125
1232
  if (wo->adminPanelConnector != NULL) {
1126
1233
  wo->adminPanelConnector->asyncShutdown();
1127
1234
  }
@@ -1133,8 +1240,7 @@ waitForExitEvent() {
1133
1240
  &fds, NULL, NULL, NULL) == -1)
1134
1241
  {
1135
1242
  int e = errno;
1136
- Agent::Fundamentals::context->abortHandlerConfig.diagnosticsDumper = NULL;
1137
- Agent::Fundamentals::abortHandlerConfigChanged();
1243
+ uninstallAbortHandlerCustomDiagnostics();
1138
1244
  throw SystemException("select() failed", e);
1139
1245
  }
1140
1246
 
@@ -1150,8 +1256,7 @@ cleanup() {
1150
1256
  P_DEBUG("Shutting down " SHORT_PROGRAM_NAME " core...");
1151
1257
  wo->appPool->destroy();
1152
1258
 
1153
- Agent::Fundamentals::context->abortHandlerConfig.diagnosticsDumper = dumpDiagnosticsOnCrash;
1154
- Agent::Fundamentals::abortHandlerConfigChanged();
1259
+ uninstallAbortHandlerCustomDiagnostics();
1155
1260
 
1156
1261
  for (unsigned i = 0; i < wo->threadWorkingObjects.size(); i++) {
1157
1262
  ThreadWorkingObjects *two = &wo->threadWorkingObjects[i];
@@ -1160,6 +1265,11 @@ cleanup() {
1160
1265
  if (wo->apiWorkingObjects.apiServer != NULL) {
1161
1266
  wo->apiWorkingObjects.bgloop->stop();
1162
1267
  }
1268
+ if (wo->telemetryCollector != NULL
1269
+ && !coreConfig->get("telemetry_collector_disabled").asBool())
1270
+ {
1271
+ wo->telemetryCollector->runOneCycle(true);
1272
+ }
1163
1273
  wo->appPool.reset();
1164
1274
  for (unsigned i = 0; i < wo->threadWorkingObjects.size(); i++) {
1165
1275
  ThreadWorkingObjects *two = &wo->threadWorkingObjects[i];
@@ -1210,12 +1320,14 @@ runCore() {
1210
1320
  initializeCurl();
1211
1321
  initializeNonPrivilegedWorkingObjects();
1212
1322
  initializeSecurityUpdateChecker();
1323
+ initializeTelemetryCollector();
1213
1324
  initializeAdminPanelConnector();
1214
1325
  prestartWebApps();
1215
1326
 
1216
1327
  UPDATE_TRACE_POINT();
1217
1328
  warnIfPassengerRootVulnerable();
1218
1329
  reportInitializationInfo();
1330
+ initializeAbortHandlerCustomerDiagnostics();
1219
1331
  mainLoop();
1220
1332
 
1221
1333
  UPDATE_TRACE_POINT();
@@ -1277,7 +1389,9 @@ int
1277
1389
  coreMain(int argc, char *argv[]) {
1278
1390
  int ret;
1279
1391
 
1280
- coreSchema = new Schema();
1392
+ coreWrapperRegistry = new WrapperRegistry::Registry();
1393
+ coreWrapperRegistry->finalize();
1394
+ coreSchema = new Schema(coreWrapperRegistry);
1281
1395
  coreConfig = new ConfigKit::Store(*coreSchema);
1282
1396
  initializeAgent(argc, &argv, SHORT_PROGRAM_NAME " core",
1283
1397
  *coreConfig, coreSchema->loggingKit.translator,
@@ -1289,5 +1403,6 @@ coreMain(int argc, char *argv[]) {
1289
1403
 
1290
1404
  ret = runCore();
1291
1405
  shutdownAgent(coreSchema, coreConfig);
1406
+ delete coreWrapperRegistry;
1292
1407
  return ret;
1293
1408
  }