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.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/.editorconfig +19 -0
- data/CHANGELOG +47 -0
- data/CONTRIBUTING.md +9 -1
- data/CONTRIBUTORS +4 -0
- data/Vagrantfile +7 -3
- data/build/agents.rb +1 -0
- data/build/misc.rb +6 -4
- data/dev/vagrant/bashrc +2 -0
- data/doc/Design and Architecture.txt +9 -7
- data/doc/Users guide Apache.idmap.txt +2 -0
- data/doc/Users guide Apache.txt +24 -4
- data/doc/Users guide Nginx.idmap.txt +4 -0
- data/doc/Users guide Nginx.txt +23 -4
- data/doc/images/code_walkthrough.jpg +0 -0
- data/doc/users_guide_snippets/installation.txt +38 -0
- data/ext/common/AgentsStarter.h +6 -1
- data/ext/common/ApplicationPool2/Common.h +17 -2
- data/ext/common/ApplicationPool2/DirectSpawner.h +5 -11
- data/ext/common/ApplicationPool2/DummySpawner.h +2 -4
- data/ext/common/ApplicationPool2/ErrorRenderer.h +119 -0
- data/ext/common/ApplicationPool2/Implementation.cpp +159 -11
- data/ext/common/ApplicationPool2/Options.h +16 -7
- data/ext/common/ApplicationPool2/Pool.h +28 -24
- data/ext/common/ApplicationPool2/Process.h +1 -9
- data/ext/common/ApplicationPool2/SmartSpawner.h +15 -18
- data/ext/common/ApplicationPool2/Spawner.h +18 -14
- data/ext/common/ApplicationPool2/SpawnerFactory.h +12 -30
- data/ext/common/Constants.h +1 -1
- data/ext/common/Exceptions.h +15 -2
- data/ext/common/UnionStation/Core.h +9 -0
- data/ext/common/Utils/JsonUtils.h +53 -0
- data/ext/common/Utils/ProcessMetricsCollector.h +1 -1
- data/ext/common/Utils/SpeedMeter.h +7 -3
- data/ext/common/Utils/SystemMetricsCollector.h +8 -6
- data/ext/common/agents/HelperAgent/Main.cpp +4 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +115 -56
- data/ext/nginx/ConfigurationCommands.c +1 -1
- data/ext/nginx/ConfigurationCommands.c.erb +6 -1
- data/ext/nginx/ContentHandler.c +2 -1
- data/ext/nginx/config +1 -1
- data/helper-scripts/node-loader.js +23 -0
- data/helper-scripts/wsgi-loader.py +12 -4
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/active_support3_extensions/init.rb +39 -78
- data/lib/phusion_passenger/constants.rb +3 -1
- data/lib/phusion_passenger/loader_shared_helpers.rb +10 -5
- data/lib/phusion_passenger/nginx/config_options.rb +3 -1
- data/lib/phusion_passenger/packaging.rb +1 -0
- data/lib/phusion_passenger/public_api.rb +108 -16
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -0
- data/lib/phusion_passenger/request_handler.rb +2 -2
- data/lib/phusion_passenger/request_handler/thread_handler.rb +28 -46
- data/lib/phusion_passenger/standalone/command.rb +8 -1
- data/lib/phusion_passenger/standalone/main.rb +0 -1
- data/lib/phusion_passenger/standalone/start_command.rb +4 -0
- data/lib/phusion_passenger/union_station/connection.rb +67 -0
- data/lib/phusion_passenger/{analytics_logger.rb → union_station/core.rb} +55 -256
- data/lib/phusion_passenger/union_station/transaction.rb +168 -0
- data/lib/phusion_passenger/utils.rb +4 -0
- data/lib/phusion_passenger/utils/lock.rb +62 -0
- data/resources/mime.types +1 -0
- data/resources/templates/error_layout.html.template +2 -0
- data/resources/templates/standalone/config.erb +1 -0
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +5 -3
- data/test/cxx/ApplicationPool2/PoolTest.cpp +13 -3
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +16 -13
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +6 -0
- data/test/cxx/FileBackedPipeTest.cpp +1 -1
- data/test/cxx/RequestHandlerTest.cpp +158 -2
- data/test/cxx/ServerInstanceDirTest.cpp +2 -0
- data/test/cxx/TestSupport.h +21 -2
- data/test/cxx/UtilsTest.cpp +1 -0
- data/test/ruby/classic_rails/loader_spec.rb +0 -1
- data/test/ruby/classic_rails/preloader_spec.rb +0 -1
- data/test/ruby/rails3.0/loader_spec.rb +2 -2
- data/test/ruby/rails3.0/preloader_spec.rb +2 -2
- data/test/ruby/rails3.1/loader_spec.rb +2 -2
- data/test/ruby/rails3.1/preloader_spec.rb +2 -2
- data/test/ruby/rails3.2/loader_spec.rb +2 -2
- data/test/ruby/rails3.2/preloader_spec.rb +2 -2
- data/test/ruby/rails4.0/loader_spec.rb +2 -2
- data/test/ruby/rails4.0/preloader_spec.rb +2 -2
- data/test/ruby/request_handler_spec.rb +8 -8
- data/test/ruby/shared/rails/{analytics_logging_extensions_sharedspec.rb → union_station_extensions_sharedspec.rb} +5 -4
- data/test/ruby/union_station_spec.rb +283 -0
- data/test/stub/wsgi/passenger_wsgi.py +41 -5
- metadata +12 -7
- metadata.gz.asc +7 -7
- data/helper-scripts/wsgi-preloader.py +0 -1
- data/lib/phusion_passenger/standalone/package_runtime_command.rb +0 -105
- 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
|
-
*
|
49
|
+
* Spawner::spawn(), such as which application is to be spawned.
|
50
50
|
*
|
51
|
-
*
|
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
|
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.
|
282
|
-
*
|
283
|
-
*
|
284
|
-
*
|
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->
|
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->
|
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
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
707
|
-
: Spawner(
|
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)
|
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)
|
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
|
-
|
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
|
-
|
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
|
1356
|
-
:
|
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>(
|
63
|
-
|
60
|
+
return boost::make_shared<SmartSpawner>(generation, preloaderCommand,
|
61
|
+
options, config);
|
64
62
|
}
|
65
63
|
|
66
64
|
public:
|
67
|
-
SpawnerFactory(const
|
68
|
-
const
|
69
|
-
|
70
|
-
|
71
|
-
|
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>(
|
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
|
-
|
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>(
|
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;
|