passenger 4.0.27 → 4.0.28
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/.gitignore +1 -0
- data/NEWS +22 -0
- data/build/preprocessor.rb +10 -0
- data/build/rpm.rb +74 -65
- data/debian.template/rules.template +8 -0
- data/dev/copy_boost_headers.rb +11 -2
- data/doc/Users guide Apache.idmap.txt +161 -145
- data/doc/Users guide Apache.txt +12 -1
- data/doc/Users guide Nginx.idmap.txt +142 -126
- data/doc/Users guide Nginx.txt +14 -1
- data/doc/Users guide Standalone.txt +1 -0
- data/doc/users_guide_snippets/environment_variables.txt +1 -1
- data/doc/users_guide_snippets/installation.txt +2 -0
- data/doc/users_guide_snippets/tips.txt +118 -0
- data/ext/apache2/Configuration.cpp +0 -6
- data/ext/apache2/Configuration.hpp +0 -5
- data/ext/apache2/ConfigurationCommands.cpp +7 -0
- data/ext/apache2/ConfigurationFields.hpp +2 -0
- data/ext/apache2/ConfigurationSetters.cpp +24 -0
- data/ext/apache2/CreateDirConfig.cpp +1 -0
- data/ext/apache2/Hooks.cpp +0 -1
- data/ext/apache2/MergeDirConfig.cpp +7 -0
- data/ext/apache2/SetHeaders.cpp +5 -1
- data/ext/boost/cregex.hpp +39 -0
- data/ext/boost/libs/regex/src/c_regex_traits.cpp +193 -0
- data/ext/boost/libs/regex/src/cpp_regex_traits.cpp +117 -0
- data/ext/boost/libs/regex/src/cregex.cpp +660 -0
- data/ext/boost/libs/regex/src/instances.cpp +32 -0
- data/ext/boost/libs/regex/src/internals.hpp +35 -0
- data/ext/boost/libs/regex/src/posix_api.cpp +296 -0
- data/ext/boost/libs/regex/src/regex.cpp +227 -0
- data/ext/boost/libs/regex/src/regex_debug.cpp +59 -0
- data/ext/boost/libs/regex/src/regex_raw_buffer.cpp +72 -0
- data/ext/boost/libs/regex/src/regex_traits_defaults.cpp +692 -0
- data/ext/boost/libs/regex/src/static_mutex.cpp +179 -0
- data/ext/boost/libs/regex/src/wc_regex_traits.cpp +301 -0
- data/ext/boost/libs/regex/src/wide_posix_api.cpp +315 -0
- data/ext/boost/libs/regex/src/winstances.cpp +35 -0
- data/ext/boost/regex.h +100 -0
- data/ext/boost/regex.hpp +37 -0
- data/ext/boost/regex/concepts.hpp +1128 -0
- data/ext/boost/regex/config.hpp +435 -0
- data/ext/boost/regex/config/borland.hpp +72 -0
- data/ext/boost/regex/config/cwchar.hpp +207 -0
- data/ext/boost/regex/mfc.hpp +190 -0
- data/ext/boost/regex/pattern_except.hpp +100 -0
- data/ext/boost/regex/pending/object_cache.hpp +165 -0
- data/ext/boost/regex/pending/static_mutex.hpp +179 -0
- data/ext/boost/regex/pending/unicode_iterator.hpp +776 -0
- data/ext/boost/regex/regex_traits.hpp +35 -0
- data/ext/boost/regex/user.hpp +93 -0
- data/ext/boost/regex/v4/basic_regex.hpp +782 -0
- data/ext/boost/regex/v4/basic_regex_creator.hpp +1571 -0
- data/ext/boost/regex/v4/basic_regex_parser.hpp +2874 -0
- data/ext/boost/regex/v4/c_regex_traits.hpp +211 -0
- data/ext/boost/regex/v4/char_regex_traits.hpp +81 -0
- data/ext/boost/regex/v4/cpp_regex_traits.hpp +1099 -0
- data/ext/boost/regex/v4/cregex.hpp +330 -0
- data/ext/boost/regex/v4/error_type.hpp +59 -0
- data/ext/boost/regex/v4/fileiter.hpp +455 -0
- data/ext/boost/regex/v4/instances.hpp +222 -0
- data/ext/boost/regex/v4/iterator_category.hpp +91 -0
- data/ext/boost/regex/v4/iterator_traits.hpp +135 -0
- data/ext/boost/regex/v4/match_flags.hpp +138 -0
- data/ext/boost/regex/v4/match_results.hpp +702 -0
- data/ext/boost/regex/v4/mem_block_cache.hpp +99 -0
- data/ext/boost/regex/v4/perl_matcher.hpp +587 -0
- data/ext/boost/regex/v4/perl_matcher_common.hpp +996 -0
- data/ext/boost/regex/v4/perl_matcher_non_recursive.hpp +1642 -0
- data/ext/boost/regex/v4/perl_matcher_recursive.hpp +991 -0
- data/ext/boost/regex/v4/primary_transform.hpp +146 -0
- data/ext/boost/regex/v4/protected_call.hpp +81 -0
- data/ext/boost/regex/v4/regbase.hpp +180 -0
- data/ext/boost/regex/v4/regex.hpp +202 -0
- data/ext/boost/regex/v4/regex_format.hpp +1156 -0
- data/ext/boost/regex/v4/regex_fwd.hpp +73 -0
- data/ext/boost/regex/v4/regex_grep.hpp +155 -0
- data/ext/boost/regex/v4/regex_iterator.hpp +201 -0
- data/ext/boost/regex/v4/regex_match.hpp +382 -0
- data/ext/boost/regex/v4/regex_merge.hpp +93 -0
- data/ext/boost/regex/v4/regex_raw_buffer.hpp +210 -0
- data/ext/boost/regex/v4/regex_replace.hpp +99 -0
- data/ext/boost/regex/v4/regex_search.hpp +217 -0
- data/ext/boost/regex/v4/regex_split.hpp +172 -0
- data/ext/boost/regex/v4/regex_token_iterator.hpp +342 -0
- data/ext/boost/regex/v4/regex_traits.hpp +189 -0
- data/ext/boost/regex/v4/regex_traits_defaults.hpp +371 -0
- data/ext/boost/regex/v4/regex_workaround.hpp +232 -0
- data/ext/boost/regex/v4/states.hpp +301 -0
- data/ext/boost/regex/v4/sub_match.hpp +512 -0
- data/ext/boost/regex/v4/syntax_type.hpp +105 -0
- data/ext/boost/regex/v4/u32regex_iterator.hpp +193 -0
- data/ext/boost/regex/v4/u32regex_token_iterator.hpp +377 -0
- data/ext/boost/regex/v4/w32_regex_traits.hpp +741 -0
- data/ext/boost/regex_fwd.hpp +33 -0
- data/ext/common/AgentsStarter.h +0 -11
- data/ext/common/ApplicationPool2/Common.h +1 -7
- data/ext/common/ApplicationPool2/DirectSpawner.h +3 -3
- data/ext/common/ApplicationPool2/Group.h +166 -69
- data/ext/common/ApplicationPool2/Implementation.cpp +55 -10
- data/ext/common/ApplicationPool2/Options.h +45 -10
- data/ext/common/ApplicationPool2/PipeWatcher.h +1 -2
- data/ext/common/ApplicationPool2/Pool.h +29 -7
- data/ext/common/ApplicationPool2/Process.h +22 -3
- data/ext/common/ApplicationPool2/Session.h +1 -0
- data/ext/common/ApplicationPool2/SmartSpawner.h +5 -10
- data/ext/common/ApplicationPool2/Spawner.h +10 -15
- data/ext/common/ApplicationPool2/SuperGroup.h +10 -9
- data/ext/common/Constants.h +1 -3
- data/ext/common/Hooks.h +193 -0
- data/ext/common/Logging.cpp +67 -2
- data/ext/common/Logging.h +23 -1
- data/ext/common/Utils.cpp +0 -21
- data/ext/common/Utils.h +0 -42
- data/ext/common/Utils/CachedFileStat.hpp +1 -1
- data/ext/common/Utils/StrIntUtils.h +61 -14
- data/ext/common/Utils/StringMap.h +4 -0
- data/ext/common/agents/HelperAgent/AgentOptions.h +4 -4
- data/ext/common/agents/HelperAgent/Main.cpp +2 -3
- data/ext/common/agents/HelperAgent/RequestHandler.h +65 -2
- data/ext/common/agents/LoggingAgent/FilterSupport.h +3 -1
- data/ext/common/agents/Watchdog/Main.cpp +8 -72
- data/ext/nginx/CacheLocationConfig.c +29 -1
- data/ext/nginx/Configuration.c +0 -12
- data/ext/nginx/Configuration.h +0 -1
- data/ext/nginx/ConfigurationCommands.c +10 -0
- data/ext/nginx/ConfigurationFields.h +2 -0
- data/ext/nginx/CreateLocationConfig.c +4 -0
- data/ext/nginx/MergeLocationConfig.c +6 -0
- data/ext/oxt/system_calls.cpp +7 -1
- data/ext/oxt/system_calls.hpp +7 -7
- data/helper-scripts/node-loader.js +6 -2
- data/helper-scripts/rack-loader.rb +5 -2
- data/helper-scripts/rack-preloader.rb +5 -2
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/apache2/config_options.rb +8 -0
- data/lib/phusion_passenger/constants.rb +0 -1
- data/lib/phusion_passenger/nginx/config_options.rb +9 -2
- data/lib/phusion_passenger/platform_info/apache.rb +2 -1
- data/lib/phusion_passenger/platform_info/compiler.rb +15 -1
- data/lib/phusion_passenger/platform_info/cxx_portability.rb +2 -0
- data/node_lib/phusion_passenger/httplib_emulation.js +85 -17
- data/node_lib/phusion_passenger/request_handler.js +10 -2
- data/rpm/Vagrantfile +32 -0
- data/rpm/get_distro_id.py +4 -0
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +2 -2
- data/test/cxx/ApplicationPool2/PoolTest.cpp +60 -9
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +2 -6
- data/test/cxx/CachedFileStatTest.cpp +5 -5
- data/test/cxx/RequestHandlerTest.cpp +3 -6
- data/test/cxx/UtilsTest.cpp +30 -0
- data/test/node/httplib_emulation_spec.js +491 -0
- data/test/node/spec_helper.js +25 -0
- metadata +78 -2
- metadata.gz.asc +7 -7
@@ -24,6 +24,7 @@
|
|
24
24
|
*/
|
25
25
|
#include <typeinfo>
|
26
26
|
#include <algorithm>
|
27
|
+
#include <utility>
|
27
28
|
#include <boost/make_shared.hpp>
|
28
29
|
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
29
30
|
#include <oxt/backtrace.hpp>
|
@@ -156,6 +157,23 @@ SuperGroup::generateSecret() const {
|
|
156
157
|
return getPool()->randomGenerator->generateAsciiString(43);
|
157
158
|
}
|
158
159
|
|
160
|
+
void
|
161
|
+
SuperGroup::runInitializationHooks() const {
|
162
|
+
getPool()->runHookScripts("after_initialize_supergroup",
|
163
|
+
boost::bind(&SuperGroup::setupInitializationOrDestructionHook, this, _1));
|
164
|
+
}
|
165
|
+
|
166
|
+
void
|
167
|
+
SuperGroup::runDestructionHooks() const {
|
168
|
+
getPool()->runHookScripts("before_destroy_supergroup",
|
169
|
+
boost::bind(&SuperGroup::setupInitializationOrDestructionHook, this, _1));
|
170
|
+
}
|
171
|
+
|
172
|
+
void
|
173
|
+
SuperGroup::setupInitializationOrDestructionHook(HookScriptOptions &options) const {
|
174
|
+
options.environment.push_back(make_pair("PASSENGER_APP_ROOT", this->options.appRoot));
|
175
|
+
}
|
176
|
+
|
159
177
|
void
|
160
178
|
SuperGroup::createInterruptableThread(const boost::function<void ()> &func, const string &name,
|
161
179
|
unsigned int stackSize)
|
@@ -216,7 +234,7 @@ SuperGroup::realDoInitialize(const Options &options, unsigned int generation) {
|
|
216
234
|
const GetWaiter &waiter = getWaitlist.front();
|
217
235
|
actions.push_back(boost::bind(waiter.callback,
|
218
236
|
SessionPtr(), exception));
|
219
|
-
getWaitlist.
|
237
|
+
getWaitlist.pop_front();
|
220
238
|
}
|
221
239
|
} else {
|
222
240
|
for (it = componentInfos.begin(); it != componentInfos.end(); it++) {
|
@@ -236,9 +254,11 @@ SuperGroup::realDoInitialize(const Options &options, unsigned int generation) {
|
|
236
254
|
verifyInvariants();
|
237
255
|
P_TRACE(2, "Done initializing SuperGroup " << inspect());
|
238
256
|
}
|
257
|
+
|
239
258
|
this_thread::disable_interruption di;
|
240
259
|
this_thread::disable_syscall_interruption dsi;
|
241
260
|
runAllActions(actions);
|
261
|
+
runInitializationHooks();
|
242
262
|
}
|
243
263
|
|
244
264
|
void
|
@@ -861,7 +881,8 @@ Group::spawnThreadRealMain(const SpawnerPtr &spawner, const Options &options, un
|
|
861
881
|
m_spawning = false;
|
862
882
|
|
863
883
|
done = done
|
864
|
-
|| (
|
884
|
+
|| (getProcessCount() >= options.minProcesses && getWaitlist.empty())
|
885
|
+
|| (options.maxProcesses != 0 && getProcessCount() >= options.maxProcesses)
|
865
886
|
|| pool->atFullCapacity(false);
|
866
887
|
m_spawning = !done;
|
867
888
|
if (done) {
|
@@ -899,7 +920,9 @@ Group::shouldSpawnForGetAction() const {
|
|
899
920
|
|
900
921
|
bool
|
901
922
|
Group::allowSpawn() const {
|
902
|
-
return isAlive()
|
923
|
+
return isAlive()
|
924
|
+
&& !poolAtFullCapacity()
|
925
|
+
&& (options.maxProcesses == 0 || getProcessCount() < options.maxProcesses);
|
903
926
|
}
|
904
927
|
|
905
928
|
void
|
@@ -1154,6 +1177,26 @@ Group::getResourceLocator() const {
|
|
1154
1177
|
return getPool()->spawnerFactory->getResourceLocator();
|
1155
1178
|
}
|
1156
1179
|
|
1180
|
+
// 'process' is not a reference so that bind(runAttachHooks, ...) causes the shared
|
1181
|
+
// pointer reference to increment.
|
1182
|
+
void
|
1183
|
+
Group::runAttachHooks(const ProcessPtr process) const {
|
1184
|
+
getPool()->runHookScripts("attached_process",
|
1185
|
+
boost::bind(&Group::setupAttachOrDetachHook, this, process, _1));
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
void
|
1189
|
+
Group::runDetachHooks(const ProcessPtr process) const {
|
1190
|
+
getPool()->runHookScripts("detached_process",
|
1191
|
+
boost::bind(&Group::setupAttachOrDetachHook, this, process, _1));
|
1192
|
+
}
|
1193
|
+
|
1194
|
+
void
|
1195
|
+
Group::setupAttachOrDetachHook(const ProcessPtr process, HookScriptOptions &options) const {
|
1196
|
+
options.environment.push_back(make_pair("PASSENGER_PROCESS_PID", toString(process->pid)));
|
1197
|
+
options.environment.push_back(make_pair("PASSENGER_APP_ROOT", this->options.appRoot));
|
1198
|
+
}
|
1199
|
+
|
1157
1200
|
string
|
1158
1201
|
Group::generateSecret(const SuperGroupPtr &superGroup) {
|
1159
1202
|
return superGroup->getPool()->randomGenerator->generateAsciiString(43);
|
@@ -1196,6 +1239,11 @@ Session::getGupid() const {
|
|
1196
1239
|
return getProcess()->gupid;
|
1197
1240
|
}
|
1198
1241
|
|
1242
|
+
int
|
1243
|
+
Session::getStickySessionId() const {
|
1244
|
+
return getProcess()->stickySessionId;
|
1245
|
+
}
|
1246
|
+
|
1199
1247
|
const GroupPtr
|
1200
1248
|
Session::getGroup() const {
|
1201
1249
|
return getProcess()->getGroup();
|
@@ -1216,11 +1264,10 @@ Session::kill(int signo) {
|
|
1216
1264
|
|
1217
1265
|
PipeWatcher::DataCallback PipeWatcher::onData;
|
1218
1266
|
|
1219
|
-
PipeWatcher::PipeWatcher(const FileDescriptor &_fd, const char *_name, pid_t _pid
|
1267
|
+
PipeWatcher::PipeWatcher(const FileDescriptor &_fd, const char *_name, pid_t _pid)
|
1220
1268
|
: fd(_fd),
|
1221
1269
|
name(_name),
|
1222
|
-
pid(_pid)
|
1223
|
-
print(_print)
|
1270
|
+
pid(_pid)
|
1224
1271
|
{
|
1225
1272
|
started = false;
|
1226
1273
|
}
|
@@ -1276,8 +1323,7 @@ PipeWatcher::threadMain() {
|
|
1276
1323
|
}
|
1277
1324
|
} else if (ret == 1 && buf[0] == '\n') {
|
1278
1325
|
UPDATE_TRACE_POINT();
|
1279
|
-
|
1280
|
-
"[App " << pid << " " << name << "] ");
|
1326
|
+
printAppOutput(pid, name, "", 0);
|
1281
1327
|
} else {
|
1282
1328
|
UPDATE_TRACE_POINT();
|
1283
1329
|
vector<StaticString> lines;
|
@@ -1287,8 +1333,7 @@ PipeWatcher::threadMain() {
|
|
1287
1333
|
}
|
1288
1334
|
split(StaticString(buf, ret2), '\n', lines);
|
1289
1335
|
foreach (const StaticString line, lines) {
|
1290
|
-
|
1291
|
-
"[App " << pid << " " << name << "] " << line);
|
1336
|
+
printAppOutput(pid, name, line.data(), line.size());
|
1292
1337
|
}
|
1293
1338
|
}
|
1294
1339
|
|
@@ -146,7 +146,10 @@ private:
|
|
146
146
|
}
|
147
147
|
|
148
148
|
public:
|
149
|
-
/*********** Spawn options that should be set manually
|
149
|
+
/*********** Spawn options that should be set manually ***********
|
150
|
+
* These are the options that are relevant while spawning an application
|
151
|
+
* process. These options are only used during spawning.
|
152
|
+
*/
|
150
153
|
|
151
154
|
/**
|
152
155
|
* The root directory of the application to spawn. In case of a Ruby on Rails
|
@@ -294,13 +297,25 @@ public:
|
|
294
297
|
bool raiseInternalError;
|
295
298
|
|
296
299
|
|
297
|
-
/*********** Per-group pool options that should be set manually
|
300
|
+
/*********** Per-group pool options that should be set manually ***********
|
301
|
+
* These options dictate how Pool will manage processes, routing, etc. within
|
302
|
+
* a single Group. These options are not process-specific, only group-specific.
|
303
|
+
*/
|
298
304
|
|
299
305
|
/**
|
300
306
|
* The minimum number of processes for the current group that the application
|
301
307
|
* pool's cleaner thread should keep around.
|
302
308
|
*/
|
303
|
-
unsigned
|
309
|
+
unsigned int minProcesses;
|
310
|
+
|
311
|
+
/**
|
312
|
+
* The maximum number of processes that may be spawned
|
313
|
+
* for this app root. This option only has effect if it's lower than
|
314
|
+
* the pool size.
|
315
|
+
*
|
316
|
+
* A value of 0 means unspecified, and has no effect.
|
317
|
+
*/
|
318
|
+
unsigned int maxProcesses;
|
304
319
|
|
305
320
|
/** The number of seconds that preloader processes may stay alive idling. */
|
306
321
|
long maxPreloaderIdleTime;
|
@@ -317,10 +332,23 @@ public:
|
|
317
332
|
*/
|
318
333
|
unsigned int maxRequestQueueSize;
|
319
334
|
|
335
|
+
/**
|
336
|
+
* The Union Station key to use in case analytics logging is enabled.
|
337
|
+
* It is used by Pool::collectAnalytics() and other administrative
|
338
|
+
* functions which are called periodically. Because they do not belong
|
339
|
+
* to any request, and they may still want to log to Union Station,
|
340
|
+
* this key is stored in the per-group options structure.
|
341
|
+
*
|
342
|
+
* It is not used on a per-request basis. Per-request analytics logging
|
343
|
+
* (and Union Station logging) uses the logger object in the `logger` field
|
344
|
+
* instead.
|
345
|
+
*/
|
346
|
+
StaticString unionStationKey;
|
347
|
+
|
320
348
|
/*-----------------*/
|
321
349
|
|
322
350
|
|
323
|
-
/*********** Per-request options that should be set manually
|
351
|
+
/*********** Per-request options that should be set manually ***********/
|
324
352
|
|
325
353
|
/** Current request host name. */
|
326
354
|
StaticString hostName;
|
@@ -335,9 +363,9 @@ public:
|
|
335
363
|
UnionStation::LoggerPtr logger;
|
336
364
|
|
337
365
|
/**
|
338
|
-
*
|
366
|
+
* A sticky session ID for routing to a specific process.
|
339
367
|
*/
|
340
|
-
|
368
|
+
unsigned int stickySessionId;
|
341
369
|
|
342
370
|
/**
|
343
371
|
* A throttling rate for file stats. When set to a non-zero value N,
|
@@ -372,7 +400,10 @@ public:
|
|
372
400
|
/*-----------------*/
|
373
401
|
|
374
402
|
|
375
|
-
/*********** Spawn options automatically set by Pool
|
403
|
+
/*********** Spawn options automatically set by Pool ***********
|
404
|
+
* These options are passed to the Spawner. The Pool::get() caller may not
|
405
|
+
* see these values.
|
406
|
+
*/
|
376
407
|
|
377
408
|
/** The secret key of the pool group that the spawned process is to belong to. */
|
378
409
|
StaticString groupSecret;
|
@@ -401,10 +432,12 @@ public:
|
|
401
432
|
raiseInternalError = false;
|
402
433
|
|
403
434
|
minProcesses = 1;
|
435
|
+
maxProcesses = 0;
|
404
436
|
maxPreloaderIdleTime = -1;
|
405
437
|
maxOutOfBandWorkInstances = 1;
|
406
438
|
maxRequestQueueSize = 100;
|
407
439
|
|
440
|
+
stickySessionId = 0;
|
408
441
|
statThrottleRate = 0;
|
409
442
|
maxRequests = 0;
|
410
443
|
noop = false;
|
@@ -494,8 +527,9 @@ public:
|
|
494
527
|
}
|
495
528
|
|
496
529
|
Options &clearPerRequestFields() {
|
497
|
-
hostName =
|
498
|
-
uri =
|
530
|
+
hostName = StaticString();
|
531
|
+
uri = StaticString();
|
532
|
+
stickySessionId = 0;
|
499
533
|
noop = false;
|
500
534
|
return clearLogger();
|
501
535
|
}
|
@@ -546,14 +580,15 @@ public:
|
|
546
580
|
appendKeyValue (vec, "logging_agent_password", loggingAgentPassword);
|
547
581
|
appendKeyValue4(vec, "debugger", debugger);
|
548
582
|
appendKeyValue4(vec, "analytics", analytics);
|
549
|
-
appendKeyValue (vec, "union_station_key", unionStationKey);
|
550
583
|
|
551
584
|
appendKeyValue (vec, "group_secret", groupSecret);
|
552
585
|
}
|
553
586
|
if (fields & PER_GROUP_POOL_OPTIONS) {
|
554
587
|
appendKeyValue3(vec, "min_processes", minProcesses);
|
588
|
+
appendKeyValue3(vec, "max_processes", maxProcesses);
|
555
589
|
appendKeyValue2(vec, "max_preloader_idle_time", maxPreloaderIdleTime);
|
556
590
|
appendKeyValue3(vec, "max_out_of_band_work_instances", maxOutOfBandWorkInstances);
|
591
|
+
appendKeyValue (vec, "union_station_key", unionStationKey);
|
557
592
|
}
|
558
593
|
|
559
594
|
/*********************************/
|
@@ -47,12 +47,11 @@ struct PipeWatcher: public boost::enable_shared_from_this<PipeWatcher> {
|
|
47
47
|
FileDescriptor fd;
|
48
48
|
const char *name;
|
49
49
|
pid_t pid;
|
50
|
-
bool print;
|
51
50
|
bool started;
|
52
51
|
boost::mutex startSyncher;
|
53
52
|
boost::condition_variable startCond;
|
54
53
|
|
55
|
-
PipeWatcher(const FileDescriptor &_fd, const char *name, pid_t pid
|
54
|
+
PipeWatcher(const FileDescriptor &_fd, const char *name, pid_t pid);
|
56
55
|
void initialize();
|
57
56
|
void start();
|
58
57
|
static void threadMain(boost::shared_ptr<PipeWatcher> self);
|
@@ -48,9 +48,9 @@
|
|
48
48
|
#include <ApplicationPool2/Options.h>
|
49
49
|
#include <UnionStation.h>
|
50
50
|
#include <Logging.h>
|
51
|
-
#include <SafeLibev.h>
|
52
51
|
#include <Exceptions.h>
|
53
52
|
#include <RandomGenerator.h>
|
53
|
+
#include <Hooks.h>
|
54
54
|
#include <Utils/Lock.h>
|
55
55
|
#include <Utils/AnsiColorConstants.h>
|
56
56
|
#include <Utils/SystemTime.h>
|
@@ -129,7 +129,6 @@ public:
|
|
129
129
|
RandomGeneratorPtr randomGenerator;
|
130
130
|
|
131
131
|
mutable boost::mutex syncher;
|
132
|
-
SafeLibev *libev;
|
133
132
|
unsigned int max;
|
134
133
|
unsigned long long maxIdleTime;
|
135
134
|
|
@@ -193,6 +192,7 @@ public:
|
|
193
192
|
*/
|
194
193
|
vector<GetWaiter> getWaitlist;
|
195
194
|
|
195
|
+
const VariantMap *agentsOptions;
|
196
196
|
DebugSupportPtr debugSupport;
|
197
197
|
|
198
198
|
static void runAllActions(const vector<Callback> &actions) {
|
@@ -247,6 +247,27 @@ public:
|
|
247
247
|
}
|
248
248
|
}
|
249
249
|
|
250
|
+
bool runHookScripts(const char *name,
|
251
|
+
const boost::function<void (HookScriptOptions &)> &setup) const
|
252
|
+
{
|
253
|
+
if (agentsOptions != NULL) {
|
254
|
+
string hookName = string("hook_") + name;
|
255
|
+
string spec = agentsOptions->get(hookName, false);
|
256
|
+
if (!spec.empty()) {
|
257
|
+
HookScriptOptions options;
|
258
|
+
options.agentsOptions = agentsOptions;
|
259
|
+
options.name = name;
|
260
|
+
options.spec = spec;
|
261
|
+
setup(options);
|
262
|
+
return Passenger::runHookScripts(options);
|
263
|
+
} else {
|
264
|
+
return true;
|
265
|
+
}
|
266
|
+
} else {
|
267
|
+
return true;
|
268
|
+
}
|
269
|
+
}
|
270
|
+
|
250
271
|
ProcessPtr findOldestIdleProcess() const {
|
251
272
|
ProcessPtr oldestIdleProcess;
|
252
273
|
|
@@ -343,7 +364,7 @@ public:
|
|
343
364
|
postLockActions.push_back(boost::bind(
|
344
365
|
getWaitlist.front().callback, SessionPtr(),
|
345
366
|
exception));
|
346
|
-
getWaitlist.
|
367
|
+
getWaitlist.pop_front();
|
347
368
|
}
|
348
369
|
}
|
349
370
|
|
@@ -385,7 +406,7 @@ public:
|
|
385
406
|
getWaitlist.reserve(getWaitlist.size() + superGroup->getWaitlist.size());
|
386
407
|
while (!superGroup->getWaitlist.empty()) {
|
387
408
|
getWaitlist.push_back(superGroup->getWaitlist.front());
|
388
|
-
superGroup->getWaitlist.
|
409
|
+
superGroup->getWaitlist.pop_front();
|
389
410
|
}
|
390
411
|
}
|
391
412
|
|
@@ -861,11 +882,11 @@ public:
|
|
861
882
|
const SuperGroupPtr getSuperGroup(const char *name);
|
862
883
|
|
863
884
|
public:
|
864
|
-
Pool(
|
885
|
+
Pool(const SpawnerFactoryPtr &spawnerFactory,
|
865
886
|
const LoggerFactoryPtr &loggerFactory = LoggerFactoryPtr(),
|
866
|
-
const RandomGeneratorPtr &randomGenerator = RandomGeneratorPtr()
|
887
|
+
const RandomGeneratorPtr &randomGenerator = RandomGeneratorPtr(),
|
888
|
+
const VariantMap *agentsOptions = NULL)
|
867
889
|
{
|
868
|
-
this->libev = libev;
|
869
890
|
this->spawnerFactory = spawnerFactory;
|
870
891
|
this->loggerFactory = loggerFactory;
|
871
892
|
if (randomGenerator != NULL) {
|
@@ -873,6 +894,7 @@ public:
|
|
873
894
|
} else {
|
874
895
|
this->randomGenerator = boost::make_shared<RandomGenerator>();
|
875
896
|
}
|
897
|
+
this->agentsOptions = agentsOptions;
|
876
898
|
|
877
899
|
lifeStatus = ALIVE;
|
878
900
|
max = 6;
|
@@ -209,7 +209,11 @@ public:
|
|
209
209
|
SafeLibev * const libev;
|
210
210
|
/** Process PID. */
|
211
211
|
pid_t pid;
|
212
|
-
/**
|
212
|
+
/** An ID that uniquely identifies this Process in the Group, for
|
213
|
+
* use in implementing sticky sessions. Set by Group::attach(). */
|
214
|
+
unsigned int stickySessionId;
|
215
|
+
/** UUID for this process, randomly generated and extremely unlikely to ever
|
216
|
+
* appear again in this universe. */
|
213
217
|
string gupid;
|
214
218
|
string connectPassword;
|
215
219
|
/** Admin socket, see class description. */
|
@@ -326,6 +330,7 @@ public:
|
|
326
330
|
: pqHandle(NULL),
|
327
331
|
libev(_libev.get()),
|
328
332
|
pid(_pid),
|
333
|
+
stickySessionId(0),
|
329
334
|
gupid(_gupid),
|
330
335
|
connectPassword(_connectPassword),
|
331
336
|
adminSocket(_adminSocket),
|
@@ -352,13 +357,13 @@ public:
|
|
352
357
|
|
353
358
|
if (_adminSocket != -1) {
|
354
359
|
PipeWatcherPtr watcher = boost::make_shared<PipeWatcher>(_adminSocket,
|
355
|
-
"stdout", pid
|
360
|
+
"stdout", pid);
|
356
361
|
watcher->initialize();
|
357
362
|
watcher->start();
|
358
363
|
}
|
359
364
|
if (_errorPipe != -1) {
|
360
365
|
PipeWatcherPtr watcher = boost::make_shared<PipeWatcher>(_errorPipe,
|
361
|
-
"stderr", pid
|
366
|
+
"stderr", pid);
|
362
367
|
watcher->initialize();
|
363
368
|
watcher->start();
|
364
369
|
}
|
@@ -537,9 +542,22 @@ public:
|
|
537
542
|
return atFullUtilization();
|
538
543
|
}
|
539
544
|
|
545
|
+
/**
|
546
|
+
* Whether we've reached the maximum number of concurrent sessions for this
|
547
|
+
* process.
|
548
|
+
*/
|
540
549
|
bool atFullUtilization() const {
|
541
550
|
return concurrency != 0 && sessions >= concurrency;
|
542
551
|
}
|
552
|
+
|
553
|
+
/**
|
554
|
+
* Whether a get() request can be routed to this process, assuming that
|
555
|
+
* the sticky session ID (if any) matches. This is only not the case
|
556
|
+
* if this process is at full utilization.
|
557
|
+
*/
|
558
|
+
bool canBeRoutedTo() const {
|
559
|
+
return !atFullUtilization();
|
560
|
+
}
|
543
561
|
|
544
562
|
/**
|
545
563
|
* Create a new communication session with this process. This will connect to one
|
@@ -588,6 +606,7 @@ public:
|
|
588
606
|
template<typename Stream>
|
589
607
|
void inspectXml(Stream &stream, bool includeSockets = true) const {
|
590
608
|
stream << "<pid>" << pid << "</pid>";
|
609
|
+
stream << "<sticky_session_id>" << stickySessionId << "</sticky_session_id>";
|
591
610
|
stream << "<gupid>" << gupid << "</gupid>";
|
592
611
|
stream << "<connect_password>" << connectPassword << "</connect_password>";
|
593
612
|
stream << "<concurrency>" << concurrency << "</concurrency>";
|