passenger 4.0.14 → 4.0.16
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.
- data.tar.gz.asc +7 -7
- data/NEWS +69 -0
- data/bin/passenger-install-apache2-module +7 -1
- data/bin/passenger-install-nginx-module +18 -1
- data/build/apache2.rb +25 -1
- data/build/basics.rb +7 -4
- data/build/debian.rb +72 -25
- data/build/nginx.rb +24 -0
- data/build/packaging.rb +45 -3
- data/debian.template/{control → control.template} +17 -8
- data/debian.template/ruby-passenger.install.template +1 -0
- data/debian.template/rules.template +9 -3
- data/dev/run_travis.sh +14 -0
- data/doc/Users guide Apache.idmap.txt +64 -48
- data/doc/Users guide Apache.txt +127 -93
- data/doc/Users guide Nginx.idmap.txt +46 -28
- data/doc/Users guide Nginx.txt +100 -12
- data/doc/images/{conservative_spawning.png → direct_spawning.png} +0 -0
- data/doc/images/{conservative_spawning.svg → direct_spawning.svg} +0 -0
- data/doc/users_guide_snippets/installation.txt +107 -66
- data/doc/users_guide_snippets/passenger_spawn_method.txt +1 -1
- data/doc/users_guide_snippets/rvm_helper_tool.txt +0 -12
- data/doc/users_guide_snippets/tips.txt +70 -3
- data/doc/users_guide_snippets/under_the_hood/page_caching_support.txt +2 -0
- data/doc/users_guide_snippets/under_the_hood/relationship_with_ruby.txt +114 -0
- data/ext/apache2/Configuration.cpp +53 -101
- data/ext/apache2/Configuration.hpp +19 -41
- data/ext/apache2/ConfigurationCommands.cpp +95 -0
- data/ext/apache2/ConfigurationCommands.cpp.erb +91 -0
- data/ext/apache2/ConfigurationFields.hpp +59 -0
- data/ext/apache2/ConfigurationFields.hpp.erb +89 -0
- data/ext/apache2/ConfigurationSetters.cpp +223 -0
- data/ext/apache2/ConfigurationSetters.cpp.erb +126 -0
- data/ext/apache2/CreateDirConfig.cpp +50 -0
- data/ext/apache2/CreateDirConfig.cpp.erb +71 -0
- data/ext/apache2/Hooks.cpp +6 -0
- data/ext/apache2/MergeDirConfig.cpp +103 -0
- data/ext/apache2/MergeDirConfig.cpp.erb +81 -0
- data/ext/common/ApplicationPool2/AppTypes.cpp +2 -0
- data/ext/common/ApplicationPool2/AppTypes.h +2 -0
- data/ext/common/ApplicationPool2/Common.h +1 -1
- data/ext/common/ApplicationPool2/Group.h +56 -7
- data/ext/common/ApplicationPool2/Implementation.cpp +133 -31
- data/ext/common/ApplicationPool2/Options.h +23 -2
- data/ext/common/ApplicationPool2/Pool.h +8 -1
- data/ext/common/ApplicationPool2/Process.h +9 -0
- data/ext/common/ApplicationPool2/Session.h +1 -0
- data/ext/common/ApplicationPool2/Spawner.h +21 -19
- data/ext/common/ApplicationPool2/SuperGroup.h +1 -1
- data/ext/common/Constants.h +21 -17
- data/ext/common/Constants.h.erb +1 -1
- data/ext/common/Exceptions.h +19 -0
- data/ext/common/ServerInstanceDir.h +8 -4
- data/ext/common/Utils.cpp +33 -1
- data/ext/common/Utils.h +14 -0
- data/ext/common/Utils/StrIntUtils.cpp +16 -0
- data/ext/common/Utils/StrIntUtils.h +5 -0
- data/ext/common/agents/HelperAgent/Main.cpp +5 -5
- data/ext/common/agents/HelperAgent/RequestHandler.h +94 -45
- data/ext/common/agents/LoggingAgent/Main.cpp +10 -26
- data/ext/common/agents/Watchdog/Main.cpp +4 -15
- data/ext/nginx/CacheLocationConfig.c +501 -0
- data/ext/nginx/CacheLocationConfig.c.erb +140 -0
- data/ext/nginx/Configuration.c +29 -453
- data/ext/nginx/Configuration.h +3 -21
- data/ext/nginx/ConfigurationCommands.c +501 -0
- data/ext/nginx/ConfigurationCommands.c.erb +136 -0
- data/ext/nginx/ConfigurationFields.h +89 -0
- data/ext/nginx/ConfigurationFields.h.erb +85 -0
- data/ext/nginx/ContentHandler.c +3 -166
- data/ext/nginx/CreateLocationConfig.c +146 -0
- data/ext/nginx/CreateLocationConfig.c.erb +70 -0
- data/ext/nginx/MergeLocationConfig.c +166 -0
- data/ext/nginx/MergeLocationConfig.c.erb +72 -0
- data/ext/nginx/config +4 -0
- data/ext/oxt/detail/tracable_exception_disabled.hpp +21 -1
- data/ext/oxt/detail/tracable_exception_enabled.hpp +4 -1
- data/ext/oxt/implementation.cpp +7 -1
- data/ext/oxt/macros.hpp +9 -7
- data/helper-scripts/backtrace-sanitizer.rb +23 -0
- data/helper-scripts/classic-rails-loader.rb +23 -0
- data/helper-scripts/classic-rails-preloader.rb +23 -0
- data/helper-scripts/download_binaries/extconf.rb +10 -5
- data/helper-scripts/meteor-loader.rb +127 -0
- data/helper-scripts/node-loader.js +1 -1
- data/helper-scripts/rack-preloader.rb +23 -0
- data/helper-scripts/system-memory-stats.py +22 -0
- data/helper-scripts/touch-dir.sh +48 -0
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/apache2/config_options.rb +104 -0
- data/lib/phusion_passenger/constants.rb +8 -0
- data/lib/phusion_passenger/native_support.rb +9 -1
- data/lib/phusion_passenger/nginx/config_options.rb +328 -0
- data/lib/phusion_passenger/packaging.rb +2 -2
- data/lib/phusion_passenger/platform_info/apache.rb +8 -0
- data/lib/phusion_passenger/platform_info/compiler.rb +2 -2
- data/lib/phusion_passenger/rails3_extensions/init.rb +19 -4
- data/lib/phusion_passenger/ruby_core_enhancements.rb +4 -1
- data/lib/phusion_passenger/standalone/app_finder.rb +3 -2
- data/lib/phusion_passenger/standalone/command.rb +1 -0
- data/lib/phusion_passenger/standalone/runtime_installer.rb +1 -6
- data/lib/phusion_passenger/standalone/runtime_locator.rb +9 -2
- data/lib/phusion_passenger/standalone/start_command.rb +45 -9
- data/lib/phusion_passenger/utils.rb +4 -1
- data/resources/templates/{nginx → installer_common}/run_installer_as_root.txt.erb +3 -1
- data/resources/templates/nginx/nginx_module_sources_not_available.txt.erb +6 -0
- data/resources/templates/standalone/config.erb +8 -8
- data/test/cxx/ApplicationPool2/PoolTest.cpp +120 -3
- data/test/cxx/RequestHandlerTest.cpp +66 -3
- data/test/integration_tests/native_packaging_spec.rb +41 -0
- data/test/integration_tests/nginx_tests.rb +1 -0
- data/test/integration_tests/standalone_tests.rb +4 -0
- data/test/ruby/shared/rails/analytics_logging_extensions_sharedspec.rb +22 -0
- data/test/stub/rails3.0/config/initializers/passenger.rb +2 -1
- data/test/stub/rails3.1/config/initializers/passenger.rb +2 -1
- data/test/stub/rails3.2/config/initializers/passenger.rb +2 -1
- data/test/stub/rails4.0/config/initializers/passenger.rb +5 -1
- data/test/stub/wsgi/passenger_wsgi.py +5 -0
- metadata +32 -7
- metadata.gz.asc +7 -7
- data/resources/templates/apache2/run_installer_as_root.txt.erb +0 -8
@@ -32,6 +32,8 @@ const AppTypeDefinition appTypeDefinitions[] = {
|
|
32
32
|
{ PAT_RACK, "rack", "config.ru", "Passenger RackApp" },
|
33
33
|
{ PAT_WSGI, "wsgi", "passenger_wsgi.py", "Passenger WsgiApp" },
|
34
34
|
{ PAT_CLASSIC_RAILS, "classic-rails", "config/environment.rb", "Passenger ClassicRailsApp" },
|
35
|
+
{ PAT_NODE, "node", "passenger_node.js", "Passenger NodeApp" },
|
36
|
+
{ PAT_METEOR, "meteor", ".meteor", "Passenger MeteorApp" },
|
35
37
|
{ PAT_NONE, NULL, NULL, NULL }
|
36
38
|
};
|
37
39
|
|
@@ -70,7 +70,7 @@ enum DisableResult {
|
|
70
70
|
DR_NOOP,
|
71
71
|
|
72
72
|
// The disabling of the process failed: an error occurred.
|
73
|
-
//
|
73
|
+
// Returned by functions and passed to the callback.
|
74
74
|
DR_ERROR,
|
75
75
|
|
76
76
|
// Indicates that the process cannot be disabled immediately
|
@@ -170,9 +170,17 @@ private:
|
|
170
170
|
static string generateSecret(const SuperGroupPtr &superGroup);
|
171
171
|
void onSessionInitiateFailure(const ProcessPtr &process, Session *session);
|
172
172
|
void onSessionClose(const ProcessPtr &process, Session *session);
|
173
|
-
|
174
|
-
|
173
|
+
|
174
|
+
/** Returns whether it is allowed to perform a new OOBW in this group. */
|
175
|
+
bool oobwAllowed() const;
|
176
|
+
/** Returns whether a new OOBW should be initiated for this process. */
|
177
|
+
bool shouldInitiateOobw(const ProcessPtr &process) const;
|
178
|
+
void maybeInitiateOobw(const ProcessPtr &process);
|
179
|
+
void lockAndMaybeInitiateOobw(const ProcessPtr &process, DisableResult result, GroupPtr self);
|
180
|
+
void initiateOobw(const ProcessPtr &process);
|
175
181
|
void spawnThreadOOBWRequest(GroupPtr self, ProcessPtr process);
|
182
|
+
void initiateNextOobwRequest();
|
183
|
+
|
176
184
|
void spawnThreadMain(GroupPtr self, SpawnerPtr spawner, Options options,
|
177
185
|
unsigned int restartsInitiated);
|
178
186
|
void spawnThreadRealMain(const SpawnerPtr &spawner, const Options &options,
|
@@ -184,6 +192,7 @@ private:
|
|
184
192
|
void wakeUpGarbageCollector();
|
185
193
|
bool poolAtFullCapacity() const;
|
186
194
|
bool anotherGroupIsWaitingForCapacity() const;
|
195
|
+
bool testOverflowRequestQueue() const;
|
187
196
|
const ResourceLocator &getResourceLocator() const;
|
188
197
|
|
189
198
|
void verifyInvariants() const {
|
@@ -233,6 +242,8 @@ private:
|
|
233
242
|
assert(process->enabled == Process::ENABLED);
|
234
243
|
assert(process->pqHandle != NULL);
|
235
244
|
assert(process->isAlive());
|
245
|
+
assert(process->oobwStatus == Process::OOBW_NOT_ACTIVE
|
246
|
+
|| process->oobwStatus == Process::OOBW_REQUESTED);
|
236
247
|
}
|
237
248
|
|
238
249
|
end = disablingProcesses.end();
|
@@ -241,6 +252,8 @@ private:
|
|
241
252
|
assert(process->enabled == Process::DISABLING);
|
242
253
|
assert(process->pqHandle == NULL);
|
243
254
|
assert(process->isAlive());
|
255
|
+
assert(process->oobwStatus == Process::OOBW_NOT_ACTIVE
|
256
|
+
|| process->oobwStatus == Process::OOBW_IN_PROGRESS);
|
244
257
|
}
|
245
258
|
|
246
259
|
end = disabledProcesses.end();
|
@@ -249,6 +262,8 @@ private:
|
|
249
262
|
assert(process->enabled == Process::DISABLED);
|
250
263
|
assert(process->pqHandle == NULL);
|
251
264
|
assert(process->isAlive());
|
265
|
+
assert(process->oobwStatus == Process::OOBW_NOT_ACTIVE
|
266
|
+
|| process->oobwStatus == Process::OOBW_IN_PROGRESS);
|
252
267
|
}
|
253
268
|
|
254
269
|
foreach (const ProcessPtr &process, detachedProcesses) {
|
@@ -305,6 +320,20 @@ private:
|
|
305
320
|
return session;
|
306
321
|
}
|
307
322
|
|
323
|
+
bool pushGetWaiter(const Options &newOptions, const GetCallback &callback) {
|
324
|
+
if (OXT_LIKELY(!testOverflowRequestQueue()
|
325
|
+
&& (newOptions.maxRequestQueueSize == 0
|
326
|
+
|| getWaitlist.size() < newOptions.maxRequestQueueSize)))
|
327
|
+
{
|
328
|
+
getWaitlist.push(GetWaiter(newOptions.copyAndPersist().clearLogger(), callback));
|
329
|
+
return true;
|
330
|
+
} else {
|
331
|
+
P_WARN("Request queue is full. Returning an error");
|
332
|
+
callback(SessionPtr(), make_shared<RequestQueueFullException>());
|
333
|
+
return false;
|
334
|
+
}
|
335
|
+
}
|
336
|
+
|
308
337
|
Process *findProcessWithLowestUtilization(const ProcessList &processes) const {
|
309
338
|
Process *result = NULL;
|
310
339
|
ProcessList::const_iterator it, end = processes.end();
|
@@ -577,14 +606,17 @@ public:
|
|
577
606
|
* process.enabled == Process::ENABLED
|
578
607
|
* process.pqHandle != NULL
|
579
608
|
* process.isAlive()
|
609
|
+
* process.oobwStatus == Process::OOBW_NOT_ACTIVE || process.oobwStatus == Process::OOBW_REQUESTED
|
580
610
|
* for all processes in disablingProcesses:
|
581
611
|
* process.enabled == Process::DISABLING
|
582
612
|
* process.pqHandle == NULL
|
583
613
|
* process.isAlive()
|
614
|
+
* process.oobwStatus == Process::OOBW_NOT_ACTIVE || process.oobwStatus == Process::OOBW_IN_PROGRESS
|
584
615
|
* for all process in disabledProcesses:
|
585
616
|
* process.enabled == Process::DISABLED
|
586
617
|
* process.pqHandle == NULL
|
587
618
|
* process.isAlive()
|
619
|
+
* process.oobwStatus == Process::OOBW_NOT_ACTIVE || process.oobwStatus == Process::OOBW_IN_PROGRESS
|
588
620
|
*/
|
589
621
|
int enabledCount;
|
590
622
|
int disablingCount;
|
@@ -723,8 +755,9 @@ public:
|
|
723
755
|
}
|
724
756
|
}
|
725
757
|
|
726
|
-
|
727
|
-
|
758
|
+
if (pushGetWaiter(newOptions, callback)) {
|
759
|
+
P_DEBUG("No session checked out yet: group is spawning or restarting");
|
760
|
+
}
|
728
761
|
return SessionPtr();
|
729
762
|
} else {
|
730
763
|
Process *process = pqueue.top();
|
@@ -734,8 +767,9 @@ public:
|
|
734
767
|
* Wait until a new one has been spawned or until
|
735
768
|
* resources have become free.
|
736
769
|
*/
|
737
|
-
|
738
|
-
|
770
|
+
if (pushGetWaiter(newOptions, callback)) {
|
771
|
+
P_DEBUG("No session checked out yet: all processes are at full capacity");
|
772
|
+
}
|
739
773
|
return SessionPtr();
|
740
774
|
} else {
|
741
775
|
P_DEBUG("Session checked out from process " << process->inspect());
|
@@ -924,7 +958,12 @@ public:
|
|
924
958
|
P_DEBUG("Disabling ENABLED process " << process->inspect() <<
|
925
959
|
"; enabledCount=" << enabledCount << ", process.sessions=" << process->sessions);
|
926
960
|
assert(enabledCount >= 0);
|
927
|
-
if (enabledCount
|
961
|
+
if (enabledCount == 1 && !allowSpawn()) {
|
962
|
+
P_WARN("Cannot disable sole enabled process in group " << name <<
|
963
|
+
" because spawning is not allowed according to the current" <<
|
964
|
+
" configuration options");
|
965
|
+
return DR_ERROR;
|
966
|
+
} else if (enabledCount <= 1 || process->sessions > 0) {
|
928
967
|
removeProcessFromList(process, enabledProcesses);
|
929
968
|
addProcessToList(process, disablingProcesses);
|
930
969
|
disableWaitlist.push_back(DisableWaiter(process, callback));
|
@@ -992,6 +1031,8 @@ public:
|
|
992
1031
|
* specific case that another get action is to be performed.
|
993
1032
|
*/
|
994
1033
|
bool shouldSpawnForGetAction() const;
|
1034
|
+
/** Whether a new process is allowed to be spawned for this group. */
|
1035
|
+
bool allowSpawn() const;
|
995
1036
|
|
996
1037
|
/** Start spawning a new process in the background, in case this
|
997
1038
|
* isn't already happening and the group isn't being restarted.
|
@@ -1032,6 +1073,14 @@ public:
|
|
1032
1073
|
return m_restarting;
|
1033
1074
|
}
|
1034
1075
|
|
1076
|
+
/**
|
1077
|
+
* Returns the number of processes in this group that should be part for the
|
1078
|
+
* MaxPoolSize constraint calculation.
|
1079
|
+
*/
|
1080
|
+
unsigned int getProcessCount() const {
|
1081
|
+
return enabledCount + disablingCount + disabledCount;
|
1082
|
+
}
|
1083
|
+
|
1035
1084
|
/**
|
1036
1085
|
* Checks whether this group is waiting for capacity on the pool to
|
1037
1086
|
* become available before it can continue processing requests.
|
@@ -62,8 +62,9 @@ copyException(const tracable_exception &e) {
|
|
62
62
|
|
63
63
|
TRY_COPY_EXCEPTION(ConfigurationException);
|
64
64
|
|
65
|
-
TRY_COPY_EXCEPTION(
|
65
|
+
TRY_COPY_EXCEPTION(RequestQueueFullException);
|
66
66
|
TRY_COPY_EXCEPTION(GetAbortedException);
|
67
|
+
TRY_COPY_EXCEPTION(SpawnException);
|
67
68
|
|
68
69
|
TRY_COPY_EXCEPTION(InvalidModeStringException);
|
69
70
|
TRY_COPY_EXCEPTION(ArgumentException);
|
@@ -104,6 +105,7 @@ rethrowException(const ExceptionPtr &e) {
|
|
104
105
|
TRY_RETHROW_EXCEPTION(ConfigurationException);
|
105
106
|
|
106
107
|
TRY_RETHROW_EXCEPTION(SpawnException);
|
108
|
+
TRY_RETHROW_EXCEPTION(RequestQueueFullException);
|
107
109
|
TRY_RETHROW_EXCEPTION(GetAbortedException);
|
108
110
|
|
109
111
|
TRY_RETHROW_EXCEPTION(InvalidModeStringException);
|
@@ -452,7 +454,7 @@ Group::onSessionClose(const ProcessPtr &process, Session *session) {
|
|
452
454
|
removeProcessFromList(process, disablingProcesses);
|
453
455
|
addProcessToList(process, disabledProcesses);
|
454
456
|
removeFromDisableWaitlist(process, DR_SUCCESS, actions);
|
455
|
-
|
457
|
+
maybeInitiateOobw(process);
|
456
458
|
}
|
457
459
|
|
458
460
|
pool->fullVerifyInvariants();
|
@@ -461,7 +463,7 @@ Group::onSessionClose(const ProcessPtr &process, Session *session) {
|
|
461
463
|
|
462
464
|
} else {
|
463
465
|
// This could change process->enabled.
|
464
|
-
|
466
|
+
maybeInitiateOobw(process);
|
465
467
|
|
466
468
|
if (!getWaitlist.empty() && process->enabled == Process::ENABLED) {
|
467
469
|
/* If there are clients on this group waiting for a process to
|
@@ -484,47 +486,111 @@ Group::requestOOBW(const ProcessPtr &process) {
|
|
484
486
|
}
|
485
487
|
}
|
486
488
|
|
489
|
+
bool
|
490
|
+
Group::oobwAllowed() const {
|
491
|
+
unsigned int oobwInstances = 0;
|
492
|
+
foreach (const ProcessPtr &process, disablingProcesses) {
|
493
|
+
if (process->oobwStatus == Process::OOBW_IN_PROGRESS) {
|
494
|
+
oobwInstances += 1;
|
495
|
+
}
|
496
|
+
}
|
497
|
+
foreach (const ProcessPtr &process, disabledProcesses) {
|
498
|
+
if (process->oobwStatus == Process::OOBW_IN_PROGRESS) {
|
499
|
+
oobwInstances += 1;
|
500
|
+
}
|
501
|
+
}
|
502
|
+
return oobwInstances < options.maxOutOfBandWorkInstances;
|
503
|
+
}
|
504
|
+
|
505
|
+
bool
|
506
|
+
Group::shouldInitiateOobw(const ProcessPtr &process) const {
|
507
|
+
return process->oobwStatus == Process::OOBW_REQUESTED
|
508
|
+
&& process->enabled != Process::DETACHED
|
509
|
+
&& process->isAlive()
|
510
|
+
&& oobwAllowed();
|
511
|
+
}
|
512
|
+
|
513
|
+
void
|
514
|
+
Group::maybeInitiateOobw(const ProcessPtr &process) {
|
515
|
+
if (shouldInitiateOobw(process)) {
|
516
|
+
initiateOobw(process);
|
517
|
+
}
|
518
|
+
}
|
519
|
+
|
487
520
|
// The 'self' parameter is for keeping the current Group object alive
|
488
521
|
void
|
489
|
-
Group::
|
522
|
+
Group::lockAndMaybeInitiateOobw(const ProcessPtr &process, DisableResult result, GroupPtr self) {
|
490
523
|
TRACE_POINT();
|
491
524
|
|
492
|
-
if (result != DR_SUCCESS && result != DR_CANCELED) {
|
493
|
-
return;
|
494
|
-
}
|
495
|
-
|
496
525
|
// Standard resource management boilerplate stuff...
|
497
526
|
PoolPtr pool = getPool();
|
498
527
|
unique_lock<boost::mutex> lock(pool->syncher);
|
499
528
|
if (OXT_UNLIKELY(!process->isAlive() || !isAlive())) {
|
500
529
|
return;
|
501
530
|
}
|
502
|
-
|
503
|
-
|
504
|
-
|
531
|
+
|
532
|
+
assert(process->oobwStatus == Process::OOBW_IN_PROGRESS);
|
533
|
+
|
534
|
+
if (result == DR_SUCCESS) {
|
535
|
+
if (process->enabled == Process::DISABLED) {
|
536
|
+
P_DEBUG("Process " << process->inspect() << " disabled; proceeding " <<
|
537
|
+
"with out-of-band work");
|
538
|
+
process->oobwStatus = Process::OOBW_REQUESTED;
|
539
|
+
if (shouldInitiateOobw(process)) {
|
540
|
+
initiateOobw(process);
|
541
|
+
} else {
|
542
|
+
// We do not re-enable the process because it's likely that the
|
543
|
+
// administrator has explicitly changed the state.
|
544
|
+
P_DEBUG("Out-of-band work for process " << process->inspect() << " aborted "
|
545
|
+
"because the process no longer requests out-of-band work");
|
546
|
+
process->oobwStatus = Process::OOBW_NOT_ACTIVE;
|
547
|
+
}
|
548
|
+
} else {
|
549
|
+
// We do not re-enable the process because it's likely that the
|
550
|
+
// administrator has explicitly changed the state.
|
551
|
+
P_DEBUG("Out-of-band work for process " << process->inspect() << " aborted "
|
552
|
+
"because the process was reenabled after disabling");
|
553
|
+
process->oobwStatus = Process::OOBW_NOT_ACTIVE;
|
554
|
+
}
|
555
|
+
} else {
|
556
|
+
P_DEBUG("Out-of-band work for process " << process->inspect() << " aborted "
|
557
|
+
"because the process could not be disabled");
|
558
|
+
process->oobwStatus = Process::OOBW_NOT_ACTIVE;
|
559
|
+
}
|
505
560
|
}
|
506
561
|
|
507
562
|
void
|
508
|
-
Group::
|
509
|
-
|
510
|
-
|
511
|
-
|
563
|
+
Group::initiateOobw(const ProcessPtr &process) {
|
564
|
+
assert(process->oobwStatus == Process::OOBW_REQUESTED);
|
565
|
+
|
566
|
+
process->oobwStatus = Process::OOBW_IN_PROGRESS;
|
567
|
+
|
568
|
+
if (process->enabled == Process::ENABLED
|
569
|
+
|| process->enabled == Process::DISABLING)
|
512
570
|
{
|
513
|
-
return;
|
514
|
-
}
|
515
|
-
if (process->enabled == Process::ENABLED) {
|
516
571
|
// We want the process to be disabled. However, disabling a process is potentially
|
517
572
|
// asynchronous, so we pass a callback which will re-aquire the lock and call this
|
518
573
|
// method again.
|
519
574
|
P_DEBUG("Disabling process " << process->inspect() << " in preparation for OOBW");
|
520
575
|
DisableResult result = disable(process,
|
521
|
-
boost::bind(&Group::
|
576
|
+
boost::bind(&Group::lockAndMaybeInitiateOobw, this,
|
522
577
|
_1, _2, shared_from_this()));
|
523
|
-
|
578
|
+
switch (result) {
|
579
|
+
case DR_SUCCESS:
|
580
|
+
// Continue code flow.
|
581
|
+
break;
|
582
|
+
case DR_DEFERRED:
|
583
|
+
// lockAndMaybeInitateOobw() will eventually be called.
|
584
|
+
return;
|
585
|
+
case DR_ERROR:
|
586
|
+
case DR_NOOP:
|
587
|
+
P_DEBUG("Out-of-band work for process " << process->inspect() << " aborted "
|
588
|
+
"because the process could not be disabled");
|
589
|
+
process->oobwStatus = Process::OOBW_NOT_ACTIVE;
|
524
590
|
return;
|
591
|
+
default:
|
592
|
+
P_BUG("Unexpected disable() result " << result);
|
525
593
|
}
|
526
|
-
} else if (process->enabled == Process::DISABLING) {
|
527
|
-
return;
|
528
594
|
}
|
529
595
|
|
530
596
|
assert(process->enabled == Process::DISABLED);
|
@@ -533,7 +599,7 @@ Group::asyncOOBWRequestIfNeeded(const ProcessPtr &process) {
|
|
533
599
|
P_DEBUG("Initiating OOBW request for process " << process->inspect());
|
534
600
|
interruptableThreads.create_thread(
|
535
601
|
boost::bind(&Group::spawnThreadOOBWRequest, this, shared_from_this(), process),
|
536
|
-
"
|
602
|
+
"OOBW request thread for process " + process->inspect(),
|
537
603
|
POOL_HELPER_THREAD_STACK_SIZE);
|
538
604
|
}
|
539
605
|
|
@@ -577,7 +643,7 @@ Group::spawnThreadOOBWRequest(GroupPtr self, ProcessPtr process) {
|
|
577
643
|
return;
|
578
644
|
}
|
579
645
|
|
580
|
-
assert(process->oobwStatus
|
646
|
+
assert(process->oobwStatus == Process::OOBW_IN_PROGRESS);
|
581
647
|
assert(process->sessions == 0);
|
582
648
|
socket = process->sessionSockets.top();
|
583
649
|
assert(socket != NULL);
|
@@ -640,8 +706,10 @@ Group::spawnThreadOOBWRequest(GroupPtr self, ProcessPtr process) {
|
|
640
706
|
enable(process, actions);
|
641
707
|
assignSessionsToGetWaiters(actions);
|
642
708
|
}
|
643
|
-
|
709
|
+
|
644
710
|
pool->fullVerifyInvariants();
|
711
|
+
|
712
|
+
initiateNextOobwRequest();
|
645
713
|
}
|
646
714
|
UPDATE_TRACE_POINT();
|
647
715
|
runAllActions(actions);
|
@@ -654,6 +722,20 @@ Group::spawnThreadOOBWRequest(GroupPtr self, ProcessPtr process) {
|
|
654
722
|
}
|
655
723
|
}
|
656
724
|
|
725
|
+
void
|
726
|
+
Group::initiateNextOobwRequest() {
|
727
|
+
ProcessList::const_iterator it, end = enabledProcesses.end();
|
728
|
+
for (it = enabledProcesses.begin(); it != end; it++) {
|
729
|
+
const ProcessPtr &process = *it;
|
730
|
+
if (shouldInitiateOobw(process)) {
|
731
|
+
// We keep an extra reference to processes to prevent premature destruction.
|
732
|
+
ProcessPtr p = process;
|
733
|
+
initiateOobw(p);
|
734
|
+
return;
|
735
|
+
}
|
736
|
+
}
|
737
|
+
}
|
738
|
+
|
657
739
|
// The 'self' parameter is for keeping the current Group object alive while this thread is running.
|
658
740
|
void
|
659
741
|
Group::spawnThreadMain(GroupPtr self, SpawnerPtr spawner, Options options, unsigned int restartsInitiated) {
|
@@ -779,7 +861,7 @@ Group::spawnThreadRealMain(const SpawnerPtr &spawner, const Options &options, un
|
|
779
861
|
m_spawning = false;
|
780
862
|
|
781
863
|
done = done
|
782
|
-
|| ((unsigned long)
|
864
|
+
|| ((unsigned long) getProcessCount() >= options.minProcesses && getWaitlist.empty())
|
783
865
|
|| pool->atFullCapacity(false);
|
784
866
|
m_spawning = !done;
|
785
867
|
if (done) {
|
@@ -803,13 +885,11 @@ Group::spawnThreadRealMain(const SpawnerPtr &spawner, const Options &options, un
|
|
803
885
|
|
804
886
|
bool
|
805
887
|
Group::shouldSpawn() const {
|
806
|
-
return
|
888
|
+
return allowSpawn()
|
807
889
|
&& (
|
808
|
-
(unsigned long)
|
890
|
+
(unsigned long) getProcessCount() < options.minProcesses
|
809
891
|
|| (enabledCount > 0 && pqueue.top()->atFullCapacity())
|
810
|
-
)
|
811
|
-
&& isAlive()
|
812
|
-
&& !poolAtFullCapacity();
|
892
|
+
);
|
813
893
|
}
|
814
894
|
|
815
895
|
bool
|
@@ -817,6 +897,11 @@ Group::shouldSpawnForGetAction() const {
|
|
817
897
|
return enabledCount == 0 || shouldSpawn();
|
818
898
|
}
|
819
899
|
|
900
|
+
bool
|
901
|
+
Group::allowSpawn() const {
|
902
|
+
return isAlive() && !poolAtFullCapacity();
|
903
|
+
}
|
904
|
+
|
820
905
|
void
|
821
906
|
Group::restart(const Options &options) {
|
822
907
|
vector<Callback> actions;
|
@@ -1035,6 +1120,18 @@ Group::anotherGroupIsWaitingForCapacity() const {
|
|
1035
1120
|
return false;
|
1036
1121
|
}
|
1037
1122
|
|
1123
|
+
bool
|
1124
|
+
Group::testOverflowRequestQueue() const {
|
1125
|
+
// This has a performance penalty, although I'm not sure whether the penalty is
|
1126
|
+
// any greater than a hash table lookup if I were to implement it in Options.
|
1127
|
+
Pool::DebugSupportPtr debug = getPool()->debugSupport;
|
1128
|
+
if (debug) {
|
1129
|
+
return debug->testOverflowRequestQueue;
|
1130
|
+
} else {
|
1131
|
+
return false;
|
1132
|
+
}
|
1133
|
+
}
|
1134
|
+
|
1038
1135
|
const ResourceLocator &
|
1039
1136
|
Group::getResourceLocator() const {
|
1040
1137
|
return getPool()->spawnerFactory->getResourceLocator();
|
@@ -1094,6 +1191,11 @@ Session::requestOOBW() {
|
|
1094
1191
|
process->getGroup()->requestOOBW(process);
|
1095
1192
|
}
|
1096
1193
|
|
1194
|
+
int
|
1195
|
+
Session::kill(int signo) {
|
1196
|
+
return getProcess()->kill(signo);
|
1197
|
+
}
|
1198
|
+
|
1097
1199
|
|
1098
1200
|
PipeWatcher::DataCallback PipeWatcher::onData;
|
1099
1201
|
|