passenger 4.0.48 → 4.0.49
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 +36 -2
- data/.travis.yml +1 -1
- data/CHANGELOG +16 -0
- data/Rakefile +0 -1
- data/build/apache2.rb +4 -4
- data/build/common_library.rb +18 -18
- data/build/cplusplus_support.rb +2 -2
- data/build/documentation.rb +1 -1
- data/build/integration_tests.rb +12 -4
- data/build/misc.rb +12 -7
- data/build/packaging.rb +14 -14
- data/build/preprocessor.rb +10 -10
- data/build/rake_extensions.rb +11 -11
- data/build/ruby_extension.rb +2 -2
- data/dev/ci/inituidgid +24 -0
- data/dev/ci/run_jenkins.sh +57 -0
- data/dev/ci/run_rpm_tests.sh +77 -0
- data/dev/{run_travis.sh → ci/run_travis.sh} +60 -4
- data/doc/Users guide Nginx.txt +2 -2
- data/doc/users_guide_snippets/environment_variables.txt +0 -2
- data/doc/users_guide_snippets/tips.txt +20 -1
- data/ext/apache2/Bucket.cpp +18 -18
- data/ext/apache2/Bucket.h +4 -4
- data/ext/apache2/Configuration.cpp +7 -7
- data/ext/apache2/Configuration.hpp +43 -43
- data/ext/apache2/DirectoryMapper.h +5 -5
- data/ext/apache2/Hooks.cpp +142 -142
- data/ext/apache2/MergeDirConfig.cpp +40 -40
- data/ext/common/Account.h +17 -17
- data/ext/common/AccountsDatabase.h +9 -9
- data/ext/common/AgentsStarter.cpp +2 -2
- data/ext/common/AgentsStarter.h +40 -40
- data/ext/common/ApplicationPool2/Common.h +10 -6
- data/ext/common/ApplicationPool2/ComponentInfo.h +2 -2
- data/ext/common/ApplicationPool2/DirectSpawner.h +17 -17
- data/ext/common/ApplicationPool2/DummySpawner.h +5 -5
- data/ext/common/ApplicationPool2/Group.h +54 -38
- data/ext/common/ApplicationPool2/Implementation.cpp +76 -49
- data/ext/common/ApplicationPool2/Options.h +98 -91
- data/ext/common/ApplicationPool2/Pool.h +70 -69
- data/ext/common/ApplicationPool2/Process.h +21 -21
- data/ext/common/ApplicationPool2/Session.h +11 -11
- data/ext/common/ApplicationPool2/SmartSpawner.h +60 -60
- data/ext/common/ApplicationPool2/Socket.h +19 -19
- data/ext/common/ApplicationPool2/Spawner.h +64 -72
- data/ext/common/ApplicationPool2/SpawnerFactory.h +4 -4
- data/ext/common/ApplicationPool2/SuperGroup.h +41 -41
- data/ext/common/BackgroundEventLoop.cpp +1 -1
- data/ext/common/BackgroundEventLoop.h +2 -2
- data/ext/common/Constants.h +1 -1
- data/ext/common/EventedBufferedInput.h +5 -5
- data/ext/common/EventedClient.h +51 -51
- data/ext/common/EventedMessageServer.h +39 -39
- data/ext/common/EventedServer.h +32 -32
- data/ext/common/Exceptions.h +23 -23
- data/ext/common/FileDescriptor.h +18 -18
- data/ext/common/Logging.cpp +1 -1
- data/ext/common/MessageClient.h +27 -27
- data/ext/common/MessageReadersWriters.h +79 -79
- data/ext/common/MessageServer.h +59 -59
- data/ext/common/RandomGenerator.h +12 -12
- data/ext/common/ResourceLocator.h +8 -8
- data/ext/common/SafeLibev.h +54 -25
- data/ext/common/ServerInstanceDir.h +31 -31
- data/ext/common/StaticString.h +50 -48
- data/ext/common/Utils.cpp +73 -78
- data/ext/common/Utils.h +6 -6
- data/ext/common/Utils/Base64.cpp +3 -3
- data/ext/common/Utils/Base64.h +7 -7
- data/ext/common/Utils/BlockingQueue.h +9 -9
- data/ext/common/Utils/BufferedIO.h +17 -17
- data/ext/common/Utils/CachedFileStat.hpp +16 -16
- data/ext/common/Utils/Dechunker.h +25 -25
- data/ext/common/Utils/FileChangeChecker.h +10 -10
- data/ext/common/Utils/MemZeroGuard.h +5 -5
- data/ext/common/Utils/MemoryBarrier.h +1 -1
- data/ext/common/Utils/MessageIO.h +61 -61
- data/ext/common/Utils/ProcessMetricsCollector.h +40 -40
- data/ext/common/Utils/ScopeGuard.h +7 -7
- data/ext/common/Utils/SpeedMeter.h +1 -1
- data/ext/common/Utils/StrIntUtils.cpp +13 -13
- data/ext/common/Utils/StrIntUtils.h +3 -3
- data/ext/common/Utils/StringScanning.h +5 -5
- data/ext/common/Utils/SystemMetricsCollector.h +2 -2
- data/ext/common/Utils/SystemTime.h +10 -10
- data/ext/common/Utils/Template.h +2 -2
- data/ext/common/Utils/Timer.h +6 -6
- data/ext/common/Utils/VariantMap.h +29 -29
- data/ext/common/agents/Base.cpp +19 -19
- data/ext/common/agents/HelperAgent/AgentOptions.h +1 -1
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +6 -6
- data/ext/common/agents/HelperAgent/Main.cpp +44 -43
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +4 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +29 -28
- data/ext/common/agents/HelperAgent/ScgiRequestParser.h +56 -50
- data/ext/common/agents/LoggingAgent/AdminController.h +8 -8
- data/ext/common/agents/LoggingAgent/DataStoreId.h +17 -17
- data/ext/common/agents/LoggingAgent/FilterSupport.h +167 -167
- data/ext/common/agents/LoggingAgent/LoggingServer.h +122 -122
- data/ext/common/agents/LoggingAgent/Main.cpp +7 -7
- data/ext/common/agents/LoggingAgent/RemoteSender.h +54 -54
- data/ext/common/agents/SpawnPreparer.cpp +4 -4
- data/ext/common/agents/TempDirToucher.c +2 -2
- data/ext/common/agents/Watchdog/AgentWatcher.cpp +47 -47
- data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +7 -7
- data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +7 -7
- data/ext/common/agents/Watchdog/Main.cpp +22 -22
- data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +9 -9
- data/ext/libeio/eio.c +1 -1
- data/ext/nginx/Configuration.c +30 -30
- data/ext/nginx/Configuration.h +1 -1
- data/ext/nginx/ContentHandler.c +54 -54
- data/ext/nginx/ContentHandler.h +3 -3
- data/ext/nginx/StaticContentHandler.c +2 -2
- data/ext/nginx/ngx_http_passenger_module.c +21 -21
- data/ext/oxt/detail/backtrace_enabled.hpp +1 -1
- data/ext/oxt/detail/context.hpp +1 -1
- data/ext/oxt/detail/spin_lock_darwin.hpp +4 -4
- data/ext/oxt/detail/spin_lock_gcc_x86.hpp +3 -3
- data/ext/oxt/detail/spin_lock_pthreads.hpp +4 -4
- data/ext/oxt/detail/tracable_exception_disabled.hpp +1 -1
- data/ext/oxt/dynamic_thread_group.hpp +18 -18
- data/ext/oxt/implementation.cpp +9 -8
- data/ext/oxt/macros.hpp +2 -2
- data/ext/oxt/system_calls.cpp +11 -11
- data/ext/oxt/system_calls.hpp +13 -13
- data/ext/oxt/thread.hpp +22 -14
- data/ext/ruby/passenger_native_support.c +55 -55
- data/lib/phusion_passenger.rb +24 -24
- data/lib/phusion_passenger/common_library.rb +2 -0
- data/lib/phusion_passenger/loader_shared_helpers.rb +18 -18
- data/lib/phusion_passenger/packaging.rb +9 -4
- data/lib/phusion_passenger/platform_info/apache.rb +45 -31
- data/lib/phusion_passenger/platform_info/compiler.rb +11 -11
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
- data/lib/phusion_passenger/request_handler/thread_handler.rb +8 -8
- data/lib/phusion_passenger/standalone/app_finder.rb +16 -16
- data/lib/phusion_passenger/standalone/command.rb +22 -22
- data/packaging/rpm/LICENSE.txt +19 -0
- data/packaging/rpm/Makefile +13 -0
- data/packaging/rpm/README.md +41 -0
- data/packaging/rpm/Vagrantfile +38 -0
- data/{rpm/Vagrantfile → packaging/rpm/Vagrantfile.centos} +0 -0
- data/packaging/rpm/build +170 -0
- data/packaging/rpm/create_project +41 -0
- data/packaging/rpm/git_update +88 -0
- data/packaging/rpm/image/Dockerfile +37 -0
- data/packaging/rpm/image/Gemfile +3 -0
- data/packaging/rpm/image/Gemfile.lock +12 -0
- data/packaging/rpm/image/RPM-GPG-KEY-amazon-ga +19 -0
- data/packaging/rpm/image/amazon2014-i386.cfg +96 -0
- data/packaging/rpm/image/amazon2014-x86_64.cfg +96 -0
- data/packaging/rpm/image/site-defaults.cfg +168 -0
- data/packaging/rpm/internal/build_tasks.rb +238 -0
- data/packaging/rpm/internal/dummygpg +11 -0
- data/packaging/rpm/internal/exec_build +42 -0
- data/packaging/rpm/internal/get_distro_arch +14 -0
- data/packaging/rpm/internal/get_distro_id +10 -0
- data/packaging/rpm/internal/git_update +27 -0
- data/packaging/rpm/internal/inituidgid +17 -0
- data/packaging/rpm/internal/my_init +344 -0
- data/packaging/rpm/internal/python27 +3 -0
- data/packaging/rpm/internal/repo_update +46 -0
- data/packaging/rpm/internal/setuser +26 -0
- data/packaging/rpm/internal/tracking_helper +40 -0
- data/packaging/rpm/jenkins_release +99 -0
- data/packaging/rpm/lib/build_tasks_support.rb +402 -0
- data/packaging/rpm/lib/preprocessor.rb +341 -0
- data/packaging/rpm/nginx_spec/404.html +119 -0
- data/packaging/rpm/nginx_spec/50x.html +119 -0
- data/packaging/rpm/nginx_spec/index.html +116 -0
- data/packaging/rpm/nginx_spec/nginx-auto-cc-gcc.patch +13 -0
- data/packaging/rpm/nginx_spec/nginx-logo.png +0 -0
- data/packaging/rpm/nginx_spec/nginx-upgrade +13 -0
- data/packaging/rpm/nginx_spec/nginx-upgrade.8 +151 -0
- data/packaging/rpm/nginx_spec/nginx.conf +131 -0
- data/packaging/rpm/nginx_spec/nginx.init +144 -0
- data/packaging/rpm/nginx_spec/nginx.logrotate +13 -0
- data/packaging/rpm/nginx_spec/nginx.service +15 -0
- data/packaging/rpm/nginx_spec/nginx.spec.template +559 -0
- data/packaging/rpm/nginx_spec/nginx.sysconfig +4 -0
- data/packaging/rpm/nginx_spec/passenger.conf +9 -0
- data/packaging/rpm/nginx_spec/poweredby.png +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/apache-passenger.conf.in +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/config.json +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger.logrotate +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger.spec.template +58 -31
- data/{rpm → packaging/rpm/passenger_spec}/passenger_dynamic_thread_group.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger_tests_default_config_example.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-GLIBC_HAVE_LONG_LONG.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-gcc47-include-sys_types.patch +0 -0
- data/packaging/rpm/repo_update +114 -0
- data/packaging/rpm/setup-system +60 -0
- data/packaging/rpm/shell +10 -0
- data/resources/templates/standalone/config.erb +3 -1
- data/test/config.json.rpm-automation +1 -1
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +11 -11
- data/test/cxx/ApplicationPool2/OptionsTest.cpp +5 -5
- data/test/cxx/ApplicationPool2/PoolTest.cpp +129 -89
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +15 -15
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +22 -22
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +11 -11
- data/test/cxx/ScgiRequestParserTest.cpp +75 -61
- data/test/cxx/UtilsTest.cpp +86 -85
- data/test/gdbinit.example +3 -0
- data/test/integration_tests/nginx_tests.rb +3 -3
- data/test/integration_tests/source_packaging_test.rb +3 -1
- data/test/stub/nginx/nginx.conf.erb +8 -1
- data/test/support/nginx_controller.rb +7 -7
- metadata +62 -17
- metadata.gz.asc +7 -7
- data/build/rpm.rb +0 -128
- data/dev/rpmtool +0 -21
- data/dev/test_rpm_packaging.sh +0 -28
- data/rpm/get_distro_id.py +0 -4
@@ -35,6 +35,7 @@
|
|
35
35
|
#include <UnionStation/Transaction.h>
|
36
36
|
#include <ApplicationPool2/Options.h>
|
37
37
|
#include <Utils/StringMap.h>
|
38
|
+
#include <Utils/VariantMap.h>
|
38
39
|
|
39
40
|
namespace tut {
|
40
41
|
struct ApplicationPool2_PoolTest;
|
@@ -119,17 +120,17 @@ enum DisableResult {
|
|
119
120
|
// The process has been successfully disabled.
|
120
121
|
// Returned by functions and passed to the callback.
|
121
122
|
DR_SUCCESS,
|
122
|
-
|
123
|
+
|
123
124
|
// The disabling of the process was canceled before completion.
|
124
125
|
// The process still exists.
|
125
126
|
// Only passed to the callback.
|
126
127
|
DR_CANCELED,
|
127
|
-
|
128
|
+
|
128
129
|
// Nothing happened: the requested process does not exist (anymore)
|
129
130
|
// or was already disabled.
|
130
131
|
// Returned by functions and passed to the callback.
|
131
132
|
DR_NOOP,
|
132
|
-
|
133
|
+
|
133
134
|
// The disabling of the process failed: an error occurred.
|
134
135
|
// Returned by functions and passed to the callback.
|
135
136
|
DR_ERROR,
|
@@ -169,7 +170,7 @@ typedef boost::function<void ()> Callback;
|
|
169
170
|
struct GetWaiter {
|
170
171
|
Options options;
|
171
172
|
GetCallback callback;
|
172
|
-
|
173
|
+
|
173
174
|
GetWaiter(const Options &o, const GetCallback &cb)
|
174
175
|
: options(o),
|
175
176
|
callback(cb)
|
@@ -186,8 +187,9 @@ struct Ticket {
|
|
186
187
|
};
|
187
188
|
|
188
189
|
struct SpawnerConfig {
|
189
|
-
// Used by error pages.
|
190
|
+
// Used by error pages and hooks.
|
190
191
|
ResourceLocator resourceLocator;
|
192
|
+
const VariantMap *agentsOptions;
|
191
193
|
|
192
194
|
// Used for Union Station logging.
|
193
195
|
UnionStation::CorePtr unionStationCore;
|
@@ -203,8 +205,10 @@ struct SpawnerConfig {
|
|
203
205
|
|
204
206
|
SpawnerConfig(const ResourceLocator &_resourceLocator,
|
205
207
|
const UnionStation::CorePtr &_unionStationCore = UnionStation::CorePtr(),
|
206
|
-
const RandomGeneratorPtr &randomGenerator = RandomGeneratorPtr()
|
208
|
+
const RandomGeneratorPtr &randomGenerator = RandomGeneratorPtr(),
|
209
|
+
const VariantMap *_agentsOptions = NULL)
|
207
210
|
: resourceLocator(_resourceLocator),
|
211
|
+
agentsOptions(_agentsOptions),
|
208
212
|
unionStationCore(_unionStationCore),
|
209
213
|
concurrency(1),
|
210
214
|
spawnerCreationSleepTime(0),
|
@@ -46,12 +46,12 @@ private:
|
|
46
46
|
pthread_t thr;
|
47
47
|
pthread_attr_t attr;
|
48
48
|
size_t stack_size = 96 * 1024;
|
49
|
-
|
49
|
+
|
50
50
|
unsigned long min_stack_size;
|
51
51
|
bool stack_min_size_defined;
|
52
52
|
bool round_stack_size;
|
53
53
|
int ret;
|
54
|
-
|
54
|
+
|
55
55
|
#ifdef PTHREAD_STACK_MIN
|
56
56
|
// PTHREAD_STACK_MIN may not be a constant macro so we need
|
57
57
|
// to evaluate it dynamically.
|
@@ -68,7 +68,7 @@ private:
|
|
68
68
|
} else {
|
69
69
|
round_stack_size = true;
|
70
70
|
}
|
71
|
-
|
71
|
+
|
72
72
|
if (round_stack_size) {
|
73
73
|
// Round stack size up to page boundary.
|
74
74
|
long page_size;
|
@@ -87,7 +87,7 @@ private:
|
|
87
87
|
stack_size = stack_size - (stack_size % page_size) + page_size;
|
88
88
|
}
|
89
89
|
}
|
90
|
-
|
90
|
+
|
91
91
|
pthread_attr_init(&attr);
|
92
92
|
pthread_attr_setdetachstate(&attr, 1);
|
93
93
|
pthread_attr_setstacksize(&attr, stack_size);
|
@@ -95,25 +95,25 @@ private:
|
|
95
95
|
pthread_attr_destroy(&attr);
|
96
96
|
return ret;
|
97
97
|
}
|
98
|
-
|
98
|
+
|
99
99
|
static void *detachProcessMain(void *arg) {
|
100
100
|
this_thread::disable_syscall_interruption dsi;
|
101
101
|
pid_t pid = (pid_t) (long) arg;
|
102
102
|
syscalls::waitpid(pid, NULL, 0);
|
103
103
|
return NULL;
|
104
104
|
}
|
105
|
-
|
105
|
+
|
106
106
|
void detachProcess(pid_t pid) {
|
107
107
|
startBackgroundThread(detachProcessMain, (void *) (long) pid);
|
108
108
|
}
|
109
|
-
|
109
|
+
|
110
110
|
vector<string> createCommand(const Options &options, const SpawnPreparationInfo &preparation,
|
111
111
|
shared_array<const char *> &args) const
|
112
112
|
{
|
113
113
|
vector<string> startCommandArgs;
|
114
114
|
string agentsDir = config->resourceLocator.getAgentsDir();
|
115
115
|
vector<string> command;
|
116
|
-
|
116
|
+
|
117
117
|
split(options.getStartCommand(config->resourceLocator), '\t', startCommandArgs);
|
118
118
|
if (startCommandArgs.empty()) {
|
119
119
|
throw RuntimeException("No startCommand given");
|
@@ -138,11 +138,11 @@ private:
|
|
138
138
|
for (unsigned int i = 1; i < startCommandArgs.size(); i++) {
|
139
139
|
command.push_back(startCommandArgs[i]);
|
140
140
|
}
|
141
|
-
|
141
|
+
|
142
142
|
createCommandArgs(command, args);
|
143
143
|
return command;
|
144
144
|
}
|
145
|
-
|
145
|
+
|
146
146
|
public:
|
147
147
|
DirectSpawner(const ServerInstanceDir::GenerationPtr &_generation,
|
148
148
|
const SpawnerConfigPtr &_config)
|
@@ -150,7 +150,7 @@ public:
|
|
150
150
|
{
|
151
151
|
generation = _generation;
|
152
152
|
}
|
153
|
-
|
153
|
+
|
154
154
|
virtual ProcessPtr spawn(const Options &options) {
|
155
155
|
TRACE_POINT();
|
156
156
|
this_thread::disable_interruption di;
|
@@ -165,7 +165,7 @@ public:
|
|
165
165
|
Pipe errorPipe = createPipe();
|
166
166
|
DebugDirPtr debugDir = boost::make_shared<DebugDir>(preparation.uid, preparation.gid);
|
167
167
|
pid_t pid;
|
168
|
-
|
168
|
+
|
169
169
|
pid = syscalls::fork();
|
170
170
|
if (pid == 0) {
|
171
171
|
setenv("PASSENGER_DEBUG_DIR", debugDir->getPath().c_str(), 1);
|
@@ -183,7 +183,7 @@ public:
|
|
183
183
|
switchUser(preparation);
|
184
184
|
setWorkingDirectory(preparation);
|
185
185
|
execvp(args[0], (char * const *) args.get());
|
186
|
-
|
186
|
+
|
187
187
|
int e = errno;
|
188
188
|
printf("!> Error\n");
|
189
189
|
printf("!> \n");
|
@@ -194,18 +194,18 @@ public:
|
|
194
194
|
fflush(stdout);
|
195
195
|
fflush(stderr);
|
196
196
|
_exit(1);
|
197
|
-
|
197
|
+
|
198
198
|
} else if (pid == -1) {
|
199
199
|
int e = errno;
|
200
200
|
throw SystemException("Cannot fork a new process", e);
|
201
|
-
|
201
|
+
|
202
202
|
} else {
|
203
203
|
UPDATE_TRACE_POINT();
|
204
204
|
ScopeGuard guard(boost::bind(nonInterruptableKillAndWaitpid, pid));
|
205
205
|
P_DEBUG("Process forked for appRoot=" << options.appRoot << ": PID " << pid);
|
206
206
|
adminSocket.first.close();
|
207
207
|
errorPipe.second.close();
|
208
|
-
|
208
|
+
|
209
209
|
NegotiationDetails details;
|
210
210
|
details.preparation = &preparation;
|
211
211
|
details.stderrCapturer =
|
@@ -221,7 +221,7 @@ public:
|
|
221
221
|
details.errorPipe = errorPipe.first;
|
222
222
|
details.options = &options;
|
223
223
|
details.debugDir = debugDir;
|
224
|
-
|
224
|
+
|
225
225
|
ProcessPtr process;
|
226
226
|
{
|
227
227
|
this_thread::restore_interruption ri(di);
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2014 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -39,17 +39,17 @@ class DummySpawner: public Spawner {
|
|
39
39
|
private:
|
40
40
|
boost::mutex lock;
|
41
41
|
unsigned int count;
|
42
|
-
|
42
|
+
|
43
43
|
public:
|
44
44
|
unsigned int cleanCount;
|
45
|
-
|
45
|
+
|
46
46
|
DummySpawner(const SpawnerConfigPtr &_config)
|
47
47
|
: Spawner(_config)
|
48
48
|
{
|
49
49
|
count = 0;
|
50
50
|
cleanCount = 0;
|
51
51
|
}
|
52
|
-
|
52
|
+
|
53
53
|
virtual ProcessPtr spawn(const Options &options) {
|
54
54
|
TRACE_POINT();
|
55
55
|
possiblyRaiseInternalError(options);
|
@@ -58,7 +58,7 @@ public:
|
|
58
58
|
SocketListPtr sockets = boost::make_shared<SocketList>();
|
59
59
|
sockets->add("main", "tcp://127.0.0.1:1234", "session", config->concurrency);
|
60
60
|
syscalls::usleep(config->spawnTime);
|
61
|
-
|
61
|
+
|
62
62
|
boost::lock_guard<boost::mutex> l(lock);
|
63
63
|
count++;
|
64
64
|
ProcessPtr process = boost::make_shared<Process>(
|
@@ -67,16 +67,16 @@ class Group: public boost::enable_shared_from_this<Group> {
|
|
67
67
|
public:
|
68
68
|
friend class Pool;
|
69
69
|
friend class SuperGroup;
|
70
|
-
|
70
|
+
|
71
71
|
struct GetAction {
|
72
72
|
GetCallback callback;
|
73
73
|
SessionPtr session;
|
74
74
|
};
|
75
|
-
|
75
|
+
|
76
76
|
struct DisableWaiter {
|
77
77
|
ProcessPtr process;
|
78
78
|
DisableCallback callback;
|
79
|
-
|
79
|
+
|
80
80
|
DisableWaiter(const ProcessPtr &_process, const DisableCallback &_callback)
|
81
81
|
: process(_process),
|
82
82
|
callback(_callback)
|
@@ -92,7 +92,7 @@ public:
|
|
92
92
|
finished(_finished)
|
93
93
|
{ }
|
94
94
|
};
|
95
|
-
|
95
|
+
|
96
96
|
/**
|
97
97
|
* Protects `lifeStatus`.
|
98
98
|
*/
|
@@ -102,7 +102,7 @@ public:
|
|
102
102
|
*
|
103
103
|
* Do not access directly, always use `isAlive()`/`getLifeStatus()` or
|
104
104
|
* through `lifetimeSyncher`.
|
105
|
-
*
|
105
|
+
*
|
106
106
|
* Invariant:
|
107
107
|
* if lifeStatus != ALIVE:
|
108
108
|
* enabledCount == 0
|
@@ -181,8 +181,8 @@ public:
|
|
181
181
|
boost::condition_variable detachedProcessesCheckerCond;
|
182
182
|
Callback shutdownCallback;
|
183
183
|
GroupPtr selfPointer;
|
184
|
-
|
185
|
-
|
184
|
+
|
185
|
+
|
186
186
|
static void _onSessionInitiateFailure(Session *session) {
|
187
187
|
ProcessPtr process = session->getProcess();
|
188
188
|
assert(process != NULL);
|
@@ -194,8 +194,9 @@ public:
|
|
194
194
|
assert(process != NULL);
|
195
195
|
process->getGroup()->onSessionClose(process, session);
|
196
196
|
}
|
197
|
-
|
197
|
+
|
198
198
|
static string generateSecret(const SuperGroupPtr &superGroup);
|
199
|
+
static string generateUuid(const SuperGroupPtr &superGroup);
|
199
200
|
void onSessionInitiateFailure(const ProcessPtr &process, Session *session);
|
200
201
|
void onSessionClose(const ProcessPtr &process, Session *session);
|
201
202
|
|
@@ -231,7 +232,7 @@ public:
|
|
231
232
|
|
232
233
|
void verifyInvariants() const {
|
233
234
|
// !a || b: logical equivalent of a IMPLIES b.
|
234
|
-
|
235
|
+
|
235
236
|
assert(enabledCount >= 0);
|
236
237
|
assert(disablingCount >= 0);
|
237
238
|
assert(disabledCount >= 0);
|
@@ -245,7 +246,7 @@ public:
|
|
245
246
|
assert(!( !getWaitlist.empty() ) || ( enabledProcesses.empty() || verifyNoRequestsOnGetWaitlistAreRoutable() ));
|
246
247
|
assert(!( enabledProcesses.empty() && !m_spawning && !restarting() && !poolAtFullCapacity() ) || ( getWaitlist.empty() ));
|
247
248
|
assert(!( !getWaitlist.empty() ) || ( !enabledProcesses.empty() || m_spawning || restarting() || poolAtFullCapacity() ));
|
248
|
-
|
249
|
+
|
249
250
|
// Verify disableWaitlist invariants.
|
250
251
|
assert((int) disableWaitlist.size() >= disablingCount);
|
251
252
|
|
@@ -319,7 +320,7 @@ public:
|
|
319
320
|
return true;
|
320
321
|
}
|
321
322
|
#endif
|
322
|
-
|
323
|
+
|
323
324
|
/**
|
324
325
|
* Sets options for this Group. Called at creation time and at restart time.
|
325
326
|
*/
|
@@ -328,8 +329,9 @@ public:
|
|
328
329
|
options.persist(newOptions);
|
329
330
|
options.clearPerRequestFields();
|
330
331
|
options.groupSecret = secret;
|
332
|
+
options.groupUuid = uuid;
|
331
333
|
}
|
332
|
-
|
334
|
+
|
333
335
|
/**
|
334
336
|
* Merges some of the new options from the latest get() request into this Group.
|
335
337
|
*/
|
@@ -339,7 +341,7 @@ public:
|
|
339
341
|
options.statThrottleRate = other.statThrottleRate;
|
340
342
|
options.maxPreloaderIdleTime = other.maxPreloaderIdleTime;
|
341
343
|
}
|
342
|
-
|
344
|
+
|
343
345
|
static void runAllActions(const vector<Callback> &actions) {
|
344
346
|
vector<Callback>::const_iterator it, end = actions.end();
|
345
347
|
for (it = actions.begin(); it != end; it++) {
|
@@ -556,7 +558,7 @@ public:
|
|
556
558
|
it->callback(it->session, ExceptionPtr());
|
557
559
|
}
|
558
560
|
}
|
559
|
-
|
561
|
+
|
560
562
|
void assignSessionsToGetWaiters(vector<Callback> &postLockActions) {
|
561
563
|
unsigned int i = 0;
|
562
564
|
bool done = false;
|
@@ -596,7 +598,7 @@ public:
|
|
596
598
|
}
|
597
599
|
clearDisableWaitlist(DR_ERROR, postLockActions);
|
598
600
|
}
|
599
|
-
|
601
|
+
|
600
602
|
void removeFromDisableWaitlist(const ProcessPtr &p, DisableResult result,
|
601
603
|
vector<Callback> &postLockActions)
|
602
604
|
{
|
@@ -657,7 +659,7 @@ public:
|
|
657
659
|
}
|
658
660
|
selfPointer.reset();
|
659
661
|
}
|
660
|
-
|
662
|
+
|
661
663
|
public:
|
662
664
|
Options options;
|
663
665
|
/** This name uniquely identifies this Group within its Pool. It can also be used as the display name. */
|
@@ -666,8 +668,13 @@ public:
|
|
666
668
|
* intra-group process communication.
|
667
669
|
*/
|
668
670
|
const string secret;
|
671
|
+
/** A UUID that's generated on Group initialization, and changes every time
|
672
|
+
* the Group receives a restart command. Allows Union Station to track app
|
673
|
+
* restarts. This information is public.
|
674
|
+
*/
|
675
|
+
string uuid;
|
669
676
|
ComponentInfo componentInfo;
|
670
|
-
|
677
|
+
|
671
678
|
/**
|
672
679
|
* Processes are categorized as enabled, disabling or disabled.
|
673
680
|
*
|
@@ -743,35 +750,35 @@ public:
|
|
743
750
|
* process.pqHandle == NULL
|
744
751
|
*/
|
745
752
|
ProcessList detachedProcesses;
|
746
|
-
|
753
|
+
|
747
754
|
/**
|
748
755
|
* get() requests for this group that cannot be immediately satisfied are
|
749
756
|
* put on this wait list, which must be processed as soon as the necessary
|
750
757
|
* resources have become free.
|
751
|
-
*
|
758
|
+
*
|
752
759
|
* ### Invariant 1 (safety)
|
753
|
-
*
|
760
|
+
*
|
754
761
|
* If requests are queued in the getWaitlist, then that's because there are
|
755
762
|
* no processes that can serve them.
|
756
|
-
*
|
763
|
+
*
|
757
764
|
* if getWaitlist is non-empty:
|
758
765
|
* enabledProcesses.empty() || (no request in getWaitlist is routeable)
|
759
766
|
*
|
760
767
|
* Here, "routeable" is defined as `route(options).process != NULL`.
|
761
|
-
*
|
768
|
+
*
|
762
769
|
* ### Invariant 2 (progress)
|
763
770
|
*
|
764
771
|
* The only reason why there are no enabled processes, while at the same time we're
|
765
772
|
* not spawning or waiting for pool capacity, is because there is nothing to do.
|
766
|
-
*
|
773
|
+
*
|
767
774
|
* if enabledProcesses.empty() && !m_spawning && !restarting() && !poolAtFullCapacity():
|
768
775
|
* getWaitlist is empty
|
769
|
-
*
|
776
|
+
*
|
770
777
|
* Equivalently:
|
771
778
|
* If requests are queued in the getWaitlist, then either we have processes that can process
|
772
779
|
* them (some time in the future), or we're actively trying to spawn processes, unless we're
|
773
780
|
* unable to do that because of resource limits.
|
774
|
-
*
|
781
|
+
*
|
775
782
|
* if getWaitlist is non-empty:
|
776
783
|
* !enabledProcesses.empty() || m_spawning || restarting() || poolAtFullCapacity()
|
777
784
|
*/
|
@@ -785,7 +792,7 @@ public:
|
|
785
792
|
* disableWaitlist.size() >= disablingCount
|
786
793
|
*/
|
787
794
|
deque<DisableWaiter> disableWaitlist;
|
788
|
-
|
795
|
+
|
789
796
|
/**
|
790
797
|
* Invariant:
|
791
798
|
* (lifeStatus == ALIVE) == (spawner != NULL)
|
@@ -840,19 +847,19 @@ public:
|
|
840
847
|
SuperGroupPtr getSuperGroup() const {
|
841
848
|
return superGroup.lock();
|
842
849
|
}
|
843
|
-
|
850
|
+
|
844
851
|
void setSuperGroup(const SuperGroupPtr &superGroup) {
|
845
852
|
assert(this->superGroup.lock() == NULL);
|
846
853
|
this->superGroup = superGroup;
|
847
854
|
}
|
848
|
-
|
855
|
+
|
849
856
|
/**
|
850
857
|
* Thread-safe.
|
851
858
|
* @pre getLifeState() != SHUT_DOWN
|
852
859
|
* @post result != NULL
|
853
860
|
*/
|
854
861
|
PoolPtr getPool() const;
|
855
|
-
|
862
|
+
|
856
863
|
// Thread-safe.
|
857
864
|
bool isAlive() const {
|
858
865
|
boost::lock_guard<boost::mutex> lock(lifetimeSyncher);
|
@@ -900,7 +907,7 @@ public:
|
|
900
907
|
}
|
901
908
|
}
|
902
909
|
}
|
903
|
-
|
910
|
+
|
904
911
|
if (OXT_UNLIKELY(newOptions.noop)) {
|
905
912
|
ProcessPtr process = boost::make_shared<Process>(
|
906
913
|
0, string(), string(),
|
@@ -911,7 +918,7 @@ public:
|
|
911
918
|
process->setGroup(shared_from_this());
|
912
919
|
return boost::make_shared<Session>(process, (Socket *) NULL);
|
913
920
|
}
|
914
|
-
|
921
|
+
|
915
922
|
if (OXT_UNLIKELY(enabledCount == 0)) {
|
916
923
|
/* We don't have any processes yet, but they're on the way.
|
917
924
|
*
|
@@ -972,6 +979,7 @@ public:
|
|
972
979
|
* afterwards if necessary, e.g. by calling `assignSessionsToGetWaiters()`.
|
973
980
|
*/
|
974
981
|
AttachResult attach(const ProcessPtr &process, vector<Callback> &postLockActions) {
|
982
|
+
TRACE_POINT();
|
975
983
|
assert(process->getGroup() == NULL || process->getGroup().get() == this);
|
976
984
|
assert(process->isAlive());
|
977
985
|
assert(isAlive());
|
@@ -1032,10 +1040,16 @@ public:
|
|
1032
1040
|
* that method over this one.
|
1033
1041
|
*/
|
1034
1042
|
void detach(const ProcessPtr &process, vector<Callback> &postLockActions) {
|
1043
|
+
TRACE_POINT();
|
1035
1044
|
assert(process->getGroup().get() == this);
|
1036
1045
|
assert(process->isAlive());
|
1037
1046
|
assert(isAlive());
|
1038
1047
|
|
1048
|
+
if (process->enabled == Process::DETACHED) {
|
1049
|
+
P_DEBUG("Detaching process " << process->inspect() << ", which was already being detached");
|
1050
|
+
return;
|
1051
|
+
}
|
1052
|
+
|
1039
1053
|
const ProcessPtr p = process; // Keep an extra reference just in case.
|
1040
1054
|
P_DEBUG("Detaching process " << process->inspect());
|
1041
1055
|
|
@@ -1048,6 +1062,7 @@ public:
|
|
1048
1062
|
removeFromDisableWaitlist(process, DR_NOOP, postLockActions);
|
1049
1063
|
}
|
1050
1064
|
} else {
|
1065
|
+
assert(process->enabled == Process::DISABLED);
|
1051
1066
|
assert(!disabledProcesses.empty());
|
1052
1067
|
removeProcessFromList(process, disabledProcesses);
|
1053
1068
|
}
|
@@ -1057,7 +1072,7 @@ public:
|
|
1057
1072
|
|
1058
1073
|
postLockActions.push_back(boost::bind(&Group::runDetachHooks, this, process));
|
1059
1074
|
}
|
1060
|
-
|
1075
|
+
|
1061
1076
|
/**
|
1062
1077
|
* Detaches all processes from this Group. This function doesn't touch
|
1063
1078
|
* getWaitlist so be sure to fix its invariants afterwards if necessary.
|
@@ -1076,7 +1091,7 @@ public:
|
|
1076
1091
|
foreach (ProcessPtr process, disabledProcesses) {
|
1077
1092
|
addProcessToList(process, detachedProcesses);
|
1078
1093
|
}
|
1079
|
-
|
1094
|
+
|
1080
1095
|
enabledProcesses.clear();
|
1081
1096
|
disablingProcesses.clear();
|
1082
1097
|
disabledProcesses.clear();
|
@@ -1087,7 +1102,7 @@ public:
|
|
1087
1102
|
clearDisableWaitlist(DR_NOOP, postLockActions);
|
1088
1103
|
startCheckingDetachedProcesses(false);
|
1089
1104
|
}
|
1090
|
-
|
1105
|
+
|
1091
1106
|
/**
|
1092
1107
|
* Marks the given process as enabled. This function doesn't touch getWaitlist
|
1093
1108
|
* so be sure to fix its invariants afterwards if necessary.
|
@@ -1110,7 +1125,7 @@ public:
|
|
1110
1125
|
P_DEBUG("Enabling ENABLED process " << process->inspect());
|
1111
1126
|
}
|
1112
1127
|
}
|
1113
|
-
|
1128
|
+
|
1114
1129
|
/**
|
1115
1130
|
* Marks the given process as disabled. Returns DR_SUCCESS, DR_DEFERRED
|
1116
1131
|
* or DR_NOOP. If the result is DR_DEFERRED, then the callback will be
|
@@ -1271,7 +1286,7 @@ public:
|
|
1271
1286
|
(unsigned long long) options.getMaxPreloaderIdleTime() * 1000000; */
|
1272
1287
|
return false;
|
1273
1288
|
}
|
1274
|
-
|
1289
|
+
|
1275
1290
|
/** Whether a new process should be spawned for this group. */
|
1276
1291
|
bool shouldSpawn() const;
|
1277
1292
|
/** Whether a new process should be spawned for this group in the
|
@@ -1288,7 +1303,7 @@ public:
|
|
1288
1303
|
&& !processUpperLimitsReached()
|
1289
1304
|
&& !poolAtFullCapacity();
|
1290
1305
|
}
|
1291
|
-
|
1306
|
+
|
1292
1307
|
bool needsRestart(const Options &options) {
|
1293
1308
|
if (m_restarting) {
|
1294
1309
|
return false;
|
@@ -1316,6 +1331,7 @@ public:
|
|
1316
1331
|
stream << "<app_root>" << escapeForXml(options.appRoot) << "</app_root>";
|
1317
1332
|
stream << "<app_type>" << escapeForXml(options.appType) << "</app_type>";
|
1318
1333
|
stream << "<environment>" << escapeForXml(options.environment) << "</environment>";
|
1334
|
+
stream << "<uuid>" << toString(uuid) << "</uuid>";
|
1319
1335
|
stream << "<enabled_process_count>" << enabledCount << "</enabled_process_count>";
|
1320
1336
|
stream << "<disabling_process_count>" << disablingCount << "</disabling_process_count>";
|
1321
1337
|
stream << "<disabled_process_count>" << disabledCount << "</disabled_process_count>";
|
@@ -1351,7 +1367,7 @@ public:
|
|
1351
1367
|
stream << "</options>";
|
1352
1368
|
|
1353
1369
|
stream << "<processes>";
|
1354
|
-
|
1370
|
+
|
1355
1371
|
for (it = enabledProcesses.begin(); it != enabledProcesses.end(); it++) {
|
1356
1372
|
stream << "<process>";
|
1357
1373
|
(*it)->inspectXml(stream, includeSecrets);
|