passenger 4.0.45 → 4.0.46

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 (94) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +19 -0
  5. data/CHANGELOG +47 -0
  6. data/CONTRIBUTING.md +9 -1
  7. data/CONTRIBUTORS +4 -0
  8. data/Vagrantfile +7 -3
  9. data/build/agents.rb +1 -0
  10. data/build/misc.rb +6 -4
  11. data/dev/vagrant/bashrc +2 -0
  12. data/doc/Design and Architecture.txt +9 -7
  13. data/doc/Users guide Apache.idmap.txt +2 -0
  14. data/doc/Users guide Apache.txt +24 -4
  15. data/doc/Users guide Nginx.idmap.txt +4 -0
  16. data/doc/Users guide Nginx.txt +23 -4
  17. data/doc/images/code_walkthrough.jpg +0 -0
  18. data/doc/users_guide_snippets/installation.txt +38 -0
  19. data/ext/common/AgentsStarter.h +6 -1
  20. data/ext/common/ApplicationPool2/Common.h +17 -2
  21. data/ext/common/ApplicationPool2/DirectSpawner.h +5 -11
  22. data/ext/common/ApplicationPool2/DummySpawner.h +2 -4
  23. data/ext/common/ApplicationPool2/ErrorRenderer.h +119 -0
  24. data/ext/common/ApplicationPool2/Implementation.cpp +159 -11
  25. data/ext/common/ApplicationPool2/Options.h +16 -7
  26. data/ext/common/ApplicationPool2/Pool.h +28 -24
  27. data/ext/common/ApplicationPool2/Process.h +1 -9
  28. data/ext/common/ApplicationPool2/SmartSpawner.h +15 -18
  29. data/ext/common/ApplicationPool2/Spawner.h +18 -14
  30. data/ext/common/ApplicationPool2/SpawnerFactory.h +12 -30
  31. data/ext/common/Constants.h +1 -1
  32. data/ext/common/Exceptions.h +15 -2
  33. data/ext/common/UnionStation/Core.h +9 -0
  34. data/ext/common/Utils/JsonUtils.h +53 -0
  35. data/ext/common/Utils/ProcessMetricsCollector.h +1 -1
  36. data/ext/common/Utils/SpeedMeter.h +7 -3
  37. data/ext/common/Utils/SystemMetricsCollector.h +8 -6
  38. data/ext/common/agents/HelperAgent/Main.cpp +4 -4
  39. data/ext/common/agents/HelperAgent/RequestHandler.h +115 -56
  40. data/ext/nginx/ConfigurationCommands.c +1 -1
  41. data/ext/nginx/ConfigurationCommands.c.erb +6 -1
  42. data/ext/nginx/ContentHandler.c +2 -1
  43. data/ext/nginx/config +1 -1
  44. data/helper-scripts/node-loader.js +23 -0
  45. data/helper-scripts/wsgi-loader.py +12 -4
  46. data/lib/phusion_passenger.rb +1 -1
  47. data/lib/phusion_passenger/active_support3_extensions/init.rb +39 -78
  48. data/lib/phusion_passenger/constants.rb +3 -1
  49. data/lib/phusion_passenger/loader_shared_helpers.rb +10 -5
  50. data/lib/phusion_passenger/nginx/config_options.rb +3 -1
  51. data/lib/phusion_passenger/packaging.rb +1 -0
  52. data/lib/phusion_passenger/public_api.rb +108 -16
  53. data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -0
  54. data/lib/phusion_passenger/request_handler.rb +2 -2
  55. data/lib/phusion_passenger/request_handler/thread_handler.rb +28 -46
  56. data/lib/phusion_passenger/standalone/command.rb +8 -1
  57. data/lib/phusion_passenger/standalone/main.rb +0 -1
  58. data/lib/phusion_passenger/standalone/start_command.rb +4 -0
  59. data/lib/phusion_passenger/union_station/connection.rb +67 -0
  60. data/lib/phusion_passenger/{analytics_logger.rb → union_station/core.rb} +55 -256
  61. data/lib/phusion_passenger/union_station/transaction.rb +168 -0
  62. data/lib/phusion_passenger/utils.rb +4 -0
  63. data/lib/phusion_passenger/utils/lock.rb +62 -0
  64. data/resources/mime.types +1 -0
  65. data/resources/templates/error_layout.html.template +2 -0
  66. data/resources/templates/standalone/config.erb +1 -0
  67. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +5 -3
  68. data/test/cxx/ApplicationPool2/PoolTest.cpp +13 -3
  69. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +16 -13
  70. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +6 -0
  71. data/test/cxx/FileBackedPipeTest.cpp +1 -1
  72. data/test/cxx/RequestHandlerTest.cpp +158 -2
  73. data/test/cxx/ServerInstanceDirTest.cpp +2 -0
  74. data/test/cxx/TestSupport.h +21 -2
  75. data/test/cxx/UtilsTest.cpp +1 -0
  76. data/test/ruby/classic_rails/loader_spec.rb +0 -1
  77. data/test/ruby/classic_rails/preloader_spec.rb +0 -1
  78. data/test/ruby/rails3.0/loader_spec.rb +2 -2
  79. data/test/ruby/rails3.0/preloader_spec.rb +2 -2
  80. data/test/ruby/rails3.1/loader_spec.rb +2 -2
  81. data/test/ruby/rails3.1/preloader_spec.rb +2 -2
  82. data/test/ruby/rails3.2/loader_spec.rb +2 -2
  83. data/test/ruby/rails3.2/preloader_spec.rb +2 -2
  84. data/test/ruby/rails4.0/loader_spec.rb +2 -2
  85. data/test/ruby/rails4.0/preloader_spec.rb +2 -2
  86. data/test/ruby/request_handler_spec.rb +8 -8
  87. data/test/ruby/shared/rails/{analytics_logging_extensions_sharedspec.rb → union_station_extensions_sharedspec.rb} +5 -4
  88. data/test/ruby/union_station_spec.rb +283 -0
  89. data/test/stub/wsgi/passenger_wsgi.py +41 -5
  90. metadata +12 -7
  91. metadata.gz.asc +7 -7
  92. data/helper-scripts/wsgi-preloader.py +0 -1
  93. data/lib/phusion_passenger/standalone/package_runtime_command.rb +0 -105
  94. data/test/ruby/analytics_logger_spec.rb +0 -283
@@ -46,13 +46,13 @@ using namespace boost;
46
46
 
47
47
  /**
48
48
  * This struct encapsulates information for ApplicationPool::get() and for
49
- * SpawnManager::spawn(), such as which application is to be spawned.
49
+ * Spawner::spawn(), such as which application is to be spawned.
50
50
  *
51
- * <h2>Privilege lowering support</h2>
51
+ * ## Privilege lowering support
52
52
  *
53
53
  * If <em>user</em> is given and isn't the empty string, then the application process
54
54
  * will run as the given username. Otherwise, the owner of the application's startup
55
- * file (e.g. config.ru or config/environment.rb) will be used.
55
+ * file (e.g. config.ru) will be used.
56
56
  *
57
57
  * If <em>group</em> is given and isn't the empty string, then the application process
58
58
  * will run as the given group name. If it's set to the special value
@@ -278,10 +278,14 @@ public:
278
278
  */
279
279
  bool loadShellEnvvars;
280
280
 
281
- /** Whether Union Station logging should be enabled. This option only affects
282
- * whether the application enables Union Station support; whether a request
283
- * actually results in data being logged to Union Station depends on whether
284
- * the 'logger' member is set.
281
+ /** Whether Union Station logging should be enabled. Enabling this option will
282
+ * result in:
283
+ *
284
+ * - The application enabling its Union Station support.
285
+ * - Periodic tasks such as `collectAnalytics()` to log things to Union Station.
286
+ *
287
+ * It does *not* necessarily result in a request logging data to Union Station.
288
+ * That depends on whether the `transaction` member is set.
285
289
  *
286
290
  * If this is set to true, then 'loggingAgentAddress', 'loggingAgentUsername'
287
291
  * and 'loggingAgentPassword' must be non-empty.
@@ -365,6 +369,11 @@ public:
365
369
  * The Union Station log transaction that this request belongs to.
366
370
  * May be the null pointer, in which case Union Station logging is
367
371
  * disabled for this request.
372
+ *
373
+ * When an Options object is passed to another thread (either direct or through
374
+ * a copy), the caller should call `detachFromUnionStationTransaction()`.
375
+ * Each Union Station transaction object is only supposed to be used in the same
376
+ * thread.
368
377
  */
369
378
  UnionStation::TransactionPtr transaction;
370
379
 
@@ -47,11 +47,8 @@
47
47
  #include <ApplicationPool2/Session.h>
48
48
  #include <ApplicationPool2/SpawnerFactory.h>
49
49
  #include <ApplicationPool2/Options.h>
50
- #include <UnionStation/Core.h>
51
- #include <UnionStation/Transaction.h>
52
50
  #include <Logging.h>
53
51
  #include <Exceptions.h>
54
- #include <RandomGenerator.h>
55
52
  #include <Hooks.h>
56
53
  #include <Utils/Lock.h>
57
54
  #include <Utils/AnsiColorConstants.h>
@@ -125,8 +122,6 @@ public:
125
122
  typedef boost::shared_ptr<DebugSupport> DebugSupportPtr;
126
123
 
127
124
  SpawnerFactoryPtr spawnerFactory;
128
- UnionStation::CorePtr unionStationCore;
129
- RandomGeneratorPtr randomGenerator;
130
125
  SystemMetricsCollector systemMetricsCollector;
131
126
  SystemMetrics systemMetrics;
132
127
 
@@ -279,6 +274,18 @@ public:
279
274
  }
280
275
  }
281
276
 
277
+ const SpawnerConfigPtr &getSpawnerConfig() const {
278
+ return spawnerFactory->getConfig();
279
+ }
280
+
281
+ const UnionStation::CorePtr &getUnionStationCore() const {
282
+ return getSpawnerConfig()->unionStationCore;
283
+ }
284
+
285
+ const RandomGeneratorPtr &getRandomGenerator() const {
286
+ return getSpawnerConfig()->randomGenerator;
287
+ }
288
+
282
289
  ProcessPtr findOldestIdleProcess(const Group *exclude = NULL) const {
283
290
  ProcessPtr oldestIdleProcess;
284
291
 
@@ -783,6 +790,7 @@ public:
783
790
  void prepareUnionStationProcessStateLogs(vector<UnionStationLogEntry> &logEntries,
784
791
  const GroupPtr &group) const
785
792
  {
793
+ const UnionStation::CorePtr &unionStationCore = getUnionStationCore();
786
794
  if (group->options.analytics && unionStationCore != NULL) {
787
795
  logEntries.push_back(UnionStationLogEntry());
788
796
  UnionStationLogEntry &entry = logEntries.back();
@@ -792,7 +800,7 @@ public:
792
800
  group->inspectXml(stream, false);
793
801
  stream << "</group>";
794
802
 
795
- entry.groupName = group->name;
803
+ entry.groupName = group->options.getAppGroupName();
796
804
  entry.category = "processes";
797
805
  entry.key = group->options.unionStationKey;
798
806
  entry.data = stream.str();
@@ -802,6 +810,7 @@ public:
802
810
  void prepareUnionStationSystemMetricsLogs(vector<UnionStationLogEntry> &logEntries,
803
811
  const GroupPtr &group) const
804
812
  {
813
+ const UnionStation::CorePtr &unionStationCore = getUnionStationCore();
805
814
  if (group->options.analytics && unionStationCore != NULL) {
806
815
  logEntries.push_back(UnionStationLogEntry());
807
816
  UnionStationLogEntry &entry = logEntries.back();
@@ -810,7 +819,7 @@ public:
810
819
  stream << "System metrics: ";
811
820
  systemMetrics.toXml(stream);
812
821
 
813
- entry.groupName = group->name;
822
+ entry.groupName = group->options.getAppGroupName();
814
823
  entry.category = "system_metrics";
815
824
  entry.key = group->options.unionStationKey;
816
825
  entry.data = stream.str();
@@ -901,15 +910,18 @@ public:
901
910
 
902
911
  l.unlock();
903
912
  UPDATE_TRACE_POINT();
904
- while (!logEntries.empty()) {
905
- UnionStationLogEntry &entry = logEntries.back();
906
- UnionStation::TransactionPtr transaction =
907
- unionStationCore->newTransaction(
908
- entry.groupName,
909
- entry.category,
910
- entry.key);
911
- transaction->message(entry.data);
912
- logEntries.pop_back();
913
+ if (!logEntries.empty()) {
914
+ const UnionStation::CorePtr &unionStationCore = getUnionStationCore();
915
+ while (!logEntries.empty()) {
916
+ UnionStationLogEntry &entry = logEntries.back();
917
+ UnionStation::TransactionPtr transaction =
918
+ unionStationCore->newTransaction(
919
+ entry.groupName,
920
+ entry.category,
921
+ entry.key);
922
+ transaction->message(entry.data);
923
+ logEntries.pop_back();
924
+ }
913
925
  }
914
926
 
915
927
  UPDATE_TRACE_POINT();
@@ -959,17 +971,9 @@ public:
959
971
 
960
972
  public:
961
973
  Pool(const SpawnerFactoryPtr &spawnerFactory,
962
- const UnionStation::CorePtr &unionStationCore = UnionStation::CorePtr(),
963
- const RandomGeneratorPtr &randomGenerator = RandomGeneratorPtr(),
964
974
  const VariantMap *agentsOptions = NULL)
965
975
  {
966
976
  this->spawnerFactory = spawnerFactory;
967
- this->unionStationCore = unionStationCore;
968
- if (randomGenerator != NULL) {
969
- this->randomGenerator = randomGenerator;
970
- } else {
971
- this->randomGenerator = boost::make_shared<RandomGenerator>();
972
- }
973
977
  this->agentsOptions = agentsOptions;
974
978
 
975
979
  try {
@@ -331,8 +331,7 @@ public:
331
331
  const FileDescriptor &_errorPipe,
332
332
  const SocketListPtr &_sockets,
333
333
  unsigned long long _spawnerCreationTime,
334
- unsigned long long _spawnStartTime,
335
- const SpawnerConfigPtr &_config = SpawnerConfigPtr())
334
+ unsigned long long _spawnStartTime)
336
335
  : pqHandle(NULL),
337
336
  pid(_pid),
338
337
  stickySessionId(0),
@@ -354,13 +353,6 @@ public:
354
353
  longRunningConnectionsAborted(false),
355
354
  shutdownStartTime(0)
356
355
  {
357
- SpawnerConfigPtr config;
358
- if (_config == NULL) {
359
- config = boost::make_shared<SpawnerConfig>();
360
- } else {
361
- config = _config;
362
- }
363
-
364
356
  if (_adminSocket != -1) {
365
357
  PipeWatcherPtr watcher = boost::make_shared<PipeWatcher>(_adminSocket,
366
358
  "stdout", pid);
@@ -99,7 +99,7 @@ private:
99
99
  vector<string> createRealPreloaderCommand(const Options &options,
100
100
  shared_array<const char *> &args)
101
101
  {
102
- string agentsDir = resourceLocator.getAgentsDir();
102
+ string agentsDir = config->resourceLocator.getAgentsDir();
103
103
  vector<string> command;
104
104
 
105
105
  if (shouldLoadShellEnvvars(options, preparation)) {
@@ -131,12 +131,13 @@ private:
131
131
  StartupDetails &details)
132
132
  {
133
133
  throwPreloaderSpawnException(msg, errorKind, details.stderrCapturer,
134
- details.debugDir);
134
+ *details.options, details.debugDir);
135
135
  }
136
136
 
137
137
  void throwPreloaderSpawnException(const string &msg,
138
138
  SpawnException::ErrorKind errorKind,
139
139
  BackgroundIOCapturerPtr &stderrCapturer,
140
+ const Options &options,
140
141
  const DebugDirPtr &debugDir)
141
142
  {
142
143
  TRACE_POINT();
@@ -185,7 +186,7 @@ private:
185
186
  errorKind);
186
187
  e.setPreloaderCommand(getPreloaderCommandString());
187
188
  annotatePreloaderException(e, debugDir);
188
- throw e;
189
+ throwSpawnException(e, options);
189
190
  }
190
191
 
191
192
  void annotatePreloaderException(SpawnException &e, const DebugDirPtr &debugDir) {
@@ -331,14 +332,14 @@ private:
331
332
  TRACE_POINT();
332
333
  try {
333
334
  string data = "You have control 1.0\n"
334
- "passenger_root: " + resourceLocator.getRoot() + "\n"
335
- "ruby_libdir: " + resourceLocator.getRubyLibDir() + "\n"
335
+ "passenger_root: " + config->resourceLocator.getRoot() + "\n"
336
+ "ruby_libdir: " + config->resourceLocator.getRubyLibDir() + "\n"
336
337
  "passenger_version: " PASSENGER_VERSION "\n"
337
338
  "generation_dir: " + generation->getPath() + "\n";
338
339
 
339
340
  vector<string> args;
340
341
  vector<string>::const_iterator it, end;
341
- details.options->toVector(args, resourceLocator, Options::SPAWN_OPTIONS);
342
+ details.options->toVector(args, config->resourceLocator, Options::SPAWN_OPTIONS);
342
343
  for (it = args.begin(); it != args.end(); it++) {
343
344
  const string &key = *it;
344
345
  it++;
@@ -507,7 +508,7 @@ private:
507
508
  SpawnException::PRELOADER_STARTUP_EXPLAINABLE_ERROR);
508
509
  e.setPreloaderCommand(getPreloaderCommandString());
509
510
  annotatePreloaderException(e, details.debugDir);
510
- throw e;
511
+ throwSpawnException(e, *details.options);
511
512
  } catch (const SystemException &e) {
512
513
  throwPreloaderSpawnException("An error occurred while starting up "
513
514
  "the preloader. It tried to report an error message, but "
@@ -608,6 +609,7 @@ private:
608
609
  "socket: " + string(e.what()),
609
610
  SpawnException::APP_STARTUP_PROTOCOL_ERROR,
610
611
  stderrCapturer,
612
+ options,
611
613
  DebugDirPtr());
612
614
  }
613
615
 
@@ -619,7 +621,7 @@ private:
619
621
  vector<string>::const_iterator it;
620
622
 
621
623
  writeExact(fd, "spawn\n", &timeout);
622
- options.toVector(args, resourceLocator, Options::SPAWN_OPTIONS);
624
+ options.toVector(args, config->resourceLocator, Options::SPAWN_OPTIONS);
623
625
  for (it = args.begin(); it != args.end(); it++) {
624
626
  const string &key = *it;
625
627
  it++;
@@ -642,6 +644,7 @@ private:
642
644
  toString(spawnedPid) + "'",
643
645
  SpawnException::APP_STARTUP_PROTOCOL_ERROR,
644
646
  stderrCapturer,
647
+ options,
645
648
  DebugDirPtr());
646
649
  }
647
650
  // TODO: we really should be checking UID.
@@ -654,6 +657,7 @@ private:
654
657
  "the same session: '" + toString(spawnedPid) + "'",
655
658
  SpawnException::APP_STARTUP_PROTOCOL_ERROR,
656
659
  stderrCapturer,
660
+ options,
657
661
  DebugDirPtr());
658
662
  }
659
663
 
@@ -699,12 +703,11 @@ protected:
699
703
  }
700
704
 
701
705
  public:
702
- SmartSpawner(const ResourceLocator &_resourceLocator,
703
- const ServerInstanceDir::GenerationPtr &_generation,
706
+ SmartSpawner(const ServerInstanceDir::GenerationPtr &_generation,
704
707
  const vector<string> &_preloaderCommand,
705
708
  const Options &_options,
706
- const SpawnerConfigPtr &_config = SpawnerConfigPtr())
707
- : Spawner(_resourceLocator),
709
+ const SpawnerConfigPtr &_config)
710
+ : Spawner(_config),
708
711
  preloaderCommand(_preloaderCommand)
709
712
  {
710
713
  if (preloaderCommand.size() < 2) {
@@ -715,12 +718,6 @@ public:
715
718
  options = _options.copyAndPersist().detachFromUnionStationTransaction();
716
719
  pid = -1;
717
720
  m_lastUsed = SystemTime::getUsec();
718
-
719
- if (_config == NULL) {
720
- config = boost::make_shared<SpawnerConfig>();
721
- } else {
722
- config = _config;
723
- }
724
721
  }
725
722
 
726
723
  virtual ~SmartSpawner() {
@@ -73,12 +73,12 @@
73
73
  #include <pwd.h>
74
74
  #include <grp.h>
75
75
  #include <dirent.h>
76
+ #include <ApplicationPool2/Common.h>
76
77
  #include <ApplicationPool2/Process.h>
77
78
  #include <ApplicationPool2/Options.h>
78
79
  #include <ApplicationPool2/PipeWatcher.h>
79
80
  #include <FileDescriptor.h>
80
81
  #include <Exceptions.h>
81
- #include <ResourceLocator.h>
82
82
  #include <StaticString.h>
83
83
  #include <ServerInstanceDir.h>
84
84
  #include <Utils.h>
@@ -384,16 +384,16 @@ private:
384
384
  TRACE_POINT();
385
385
  try {
386
386
  string data = "You have control 1.0\n"
387
- "passenger_root: " + resourceLocator.getRoot() + "\n"
387
+ "passenger_root: " + config->resourceLocator.getRoot() + "\n"
388
388
  "passenger_version: " PASSENGER_VERSION "\n"
389
- "ruby_libdir: " + resourceLocator.getRubyLibDir() + "\n"
389
+ "ruby_libdir: " + config->resourceLocator.getRubyLibDir() + "\n"
390
390
  "generation_dir: " + generation->getPath() + "\n"
391
391
  "gupid: " + details.gupid + "\n"
392
392
  "connect_password: " + details.connectPassword + "\n";
393
393
 
394
394
  vector<string> args;
395
395
  vector<string>::const_iterator it, end;
396
- details.options->toVector(args, resourceLocator, Options::SPAWN_OPTIONS);
396
+ details.options->toVector(args, config->resourceLocator, Options::SPAWN_OPTIONS);
397
397
  for (it = args.begin(); it != args.end(); it++) {
398
398
  const string &key = *it;
399
399
  it++;
@@ -530,14 +530,12 @@ private:
530
530
  details.pid,
531
531
  details.gupid, details.connectPassword,
532
532
  details.adminSocket, details.errorPipe,
533
- sockets, creationTime, details.spawnStartTime,
534
- config);
533
+ sockets, creationTime, details.spawnStartTime);
535
534
  process->codeRevision = details.preparation->codeRevision;
536
535
  return process;
537
536
  }
538
537
 
539
538
  protected:
540
- ResourceLocator resourceLocator;
541
539
  ServerInstanceDir::GenerationPtr generation;
542
540
  SpawnerConfigPtr config;
543
541
 
@@ -730,6 +728,11 @@ protected:
730
728
  true,
731
729
  errorKind);
732
730
  annotateAppSpawnException(e, details);
731
+ throwSpawnException(e, *details.options);
732
+ }
733
+
734
+ void throwSpawnException(SpawnException &e, const Options &options) {
735
+ processAndLogNewSpawnException(e, options, config);
733
736
  throw e;
734
737
  }
735
738
 
@@ -796,7 +799,7 @@ protected:
796
799
  }
797
800
  }
798
801
 
799
- SpawnPreparationInfo prepareSpawn(const Options &options) const {
802
+ SpawnPreparationInfo prepareSpawn(const Options &options) {
800
803
  TRACE_POINT();
801
804
  SpawnPreparationInfo info;
802
805
  prepareChroot(info, options);
@@ -806,7 +809,7 @@ protected:
806
809
  return info;
807
810
  }
808
811
 
809
- void prepareChroot(SpawnPreparationInfo &info, const Options &options) const {
812
+ void prepareChroot(SpawnPreparationInfo &info, const Options &options) {
810
813
  TRACE_POINT();
811
814
  info.appRoot = absolutizePath(options.appRoot);
812
815
  if (options.preexecChroot.empty()) {
@@ -815,10 +818,11 @@ protected:
815
818
  info.chrootDir = absolutizePath(options.preexecChroot);
816
819
  }
817
820
  if (info.appRoot != info.chrootDir && startsWith(info.appRoot, info.chrootDir + "/")) {
818
- throw SpawnException("Invalid configuration: '" + info.chrootDir +
821
+ SpawnException e("Invalid configuration: '" + info.chrootDir +
819
822
  "' has been configured as the chroot jail, but the application " +
820
823
  "root directory '" + info.appRoot + "' is not a subdirectory of the " +
821
824
  "chroot directory, which it must be.");
825
+ throwSpawnException(e, options);
822
826
  }
823
827
  if (info.appRoot == info.chrootDir) {
824
828
  info.appRootInsideChroot = "/";
@@ -1042,7 +1046,7 @@ protected:
1042
1046
 
1043
1047
  appendNullTerminatedKeyValue(result, "IN_PASSENGER", "1");
1044
1048
  appendNullTerminatedKeyValue(result, "PYTHONUNBUFFERED", "1");
1045
- appendNullTerminatedKeyValue(result, "NODE_PATH", resourceLocator.getNodeLibDir());
1049
+ appendNullTerminatedKeyValue(result, "NODE_PATH", config->resourceLocator.getNodeLibDir());
1046
1050
  appendNullTerminatedKeyValue(result, "RAILS_ENV", options.environment);
1047
1051
  appendNullTerminatedKeyValue(result, "RACK_ENV", options.environment);
1048
1052
  appendNullTerminatedKeyValue(result, "WSGI_ENV", options.environment);
@@ -1313,7 +1317,7 @@ protected:
1313
1317
  attributes["html"] == "true",
1314
1318
  SpawnException::APP_STARTUP_EXPLAINABLE_ERROR);
1315
1319
  annotateAppSpawnException(e, details);
1316
- throw e;
1320
+ throwSpawnException(e, *details.options);
1317
1321
  } catch (const SystemException &e) {
1318
1322
  throwAppSpawnException("An error occurred while starting the "
1319
1323
  "web application. It tried to report an error message, but "
@@ -1352,8 +1356,8 @@ public:
1352
1356
  */
1353
1357
  const unsigned long long creationTime;
1354
1358
 
1355
- Spawner(const ResourceLocator &_resourceLocator)
1356
- : resourceLocator(_resourceLocator),
1359
+ Spawner(const SpawnerConfigPtr &_config)
1360
+ : config(_config),
1357
1361
  creationTime(SystemTime::getUsec())
1358
1362
  { }
1359
1363
 
@@ -40,15 +40,13 @@ using namespace oxt;
40
40
 
41
41
  class SpawnerFactory {
42
42
  private:
43
- ResourceLocator resourceLocator;
44
43
  ServerInstanceDir::GenerationPtr generation;
45
- RandomGeneratorPtr randomGenerator;
46
44
  boost::mutex syncher;
47
45
  SpawnerConfigPtr config;
48
46
  DummySpawnerPtr dummySpawner;
49
47
 
50
48
  SpawnerPtr tryCreateSmartSpawner(const Options &options) {
51
- string dir = resourceLocator.getHelperScriptsDir();
49
+ string dir = config->resourceLocator.getHelperScriptsDir();
52
50
  vector<string> preloaderCommand;
53
51
  if (options.appType == "classic-rails") {
54
52
  preloaderCommand.push_back(options.ruby);
@@ -59,23 +57,16 @@ private:
59
57
  } else {
60
58
  return SpawnerPtr();
61
59
  }
62
- return boost::make_shared<SmartSpawner>(resourceLocator,
63
- generation, preloaderCommand, options, config);
60
+ return boost::make_shared<SmartSpawner>(generation, preloaderCommand,
61
+ options, config);
64
62
  }
65
63
 
66
64
  public:
67
- SpawnerFactory(const ResourceLocator &_resourceLocator,
68
- const ServerInstanceDir::GenerationPtr &_generation,
69
- const SpawnerConfigPtr &_config = SpawnerConfigPtr())
70
- : resourceLocator(_resourceLocator),
71
- generation(_generation)
72
- {
73
- if (_config == NULL) {
74
- config = boost::make_shared<SpawnerConfig>();
75
- } else {
76
- config = _config;
77
- }
78
- }
65
+ SpawnerFactory(const ServerInstanceDir::GenerationPtr &_generation,
66
+ const SpawnerConfigPtr &_config)
67
+ : generation(_generation),
68
+ config(_config)
69
+ { }
79
70
 
80
71
  virtual ~SpawnerFactory() { }
81
72
 
@@ -83,13 +74,12 @@ public:
83
74
  if (options.spawnMethod == "smart" || options.spawnMethod == "smart-lv2") {
84
75
  SpawnerPtr spawner = tryCreateSmartSpawner(options);
85
76
  if (spawner == NULL) {
86
- spawner = boost::make_shared<DirectSpawner>(resourceLocator,
87
- generation, config);
77
+ spawner = boost::make_shared<DirectSpawner>(generation, config);
88
78
  }
89
79
  return spawner;
90
80
  } else if (options.spawnMethod == "direct" || options.spawnMethod == "conservative") {
91
81
  boost::shared_ptr<DirectSpawner> spawner = boost::make_shared<DirectSpawner>(
92
- resourceLocator, generation, config);
82
+ generation, config);
93
83
  return spawner;
94
84
  } else if (options.spawnMethod == "dummy") {
95
85
  syscalls::usleep(config->spawnerCreationSleepTime);
@@ -107,7 +97,7 @@ public:
107
97
  DummySpawnerPtr getDummySpawner() {
108
98
  boost::lock_guard<boost::mutex> l(syncher);
109
99
  if (dummySpawner == NULL) {
110
- dummySpawner = boost::make_shared<DummySpawner>(resourceLocator, config);
100
+ dummySpawner = boost::make_shared<DummySpawner>(config);
111
101
  }
112
102
  return dummySpawner;
113
103
  }
@@ -115,17 +105,9 @@ public:
115
105
  /**
116
106
  * All created Spawner objects share the same SpawnerConfig object.
117
107
  */
118
- SpawnerConfigPtr getConfig() const {
108
+ const SpawnerConfigPtr &getConfig() const {
119
109
  return config;
120
110
  }
121
-
122
- RandomGeneratorPtr getRandomGenerator() const {
123
- return randomGenerator;
124
- }
125
-
126
- const ResourceLocator &getResourceLocator() const {
127
- return resourceLocator;
128
- }
129
111
  };
130
112
 
131
113
  typedef boost::shared_ptr<SpawnerFactory> SpawnerFactoryPtr;