passenger 3.9.2.beta → 4.0.0.rc4
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/.travis.yml +3 -0
- data/NEWS +77 -7
- data/README.md +3 -11
- data/bin/passenger-install-apache2-module +24 -20
- data/bin/passenger-install-nginx-module +25 -23
- data/build/agents.rb +11 -0
- data/build/apache2.rb +9 -5
- data/build/basics.rb +37 -30
- data/build/common_library.rb +4 -1
- data/build/cplusplus_support.rb +5 -5
- data/build/cxx_tests.rb +28 -8
- data/build/integration_tests.rb +6 -3
- data/build/nginx.rb +3 -3
- data/build/packaging.rb +95 -57
- data/build/ruby_extension.rb +34 -21
- data/build/ruby_tests.rb +4 -2
- data/build/test_basics.rb +1 -1
- data/dev/run_travis.sh +36 -1
- data/doc/Users guide Apache.html +425 -308
- data/doc/Users guide Apache.idmap.txt +78 -70
- data/doc/Users guide Apache.index.sqlite3 +0 -0
- data/doc/Users guide Apache.txt +33 -92
- data/doc/Users guide Nginx.html +519 -220
- data/doc/Users guide Nginx.idmap.txt +78 -60
- data/doc/Users guide Nginx.txt +115 -26
- data/doc/Users guide Standalone.html +8 -2
- data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +1 -7
- data/doc/users_guide_snippets/installation.txt +167 -22
- data/doc/users_guide_snippets/rackup_specifications.txt +4 -0
- data/doc/users_guide_snippets/since_version.txt +1 -0
- data/doc/users_guide_snippets/support_information.txt +3 -7
- data/doc/users_guide_snippets/tips.txt +0 -24
- data/ext/apache2/Configuration.cpp +11 -33
- data/ext/apache2/Configuration.hpp +3 -18
- data/ext/apache2/DirectoryMapper.h +20 -70
- data/ext/apache2/Hooks.cpp +2 -2
- data/ext/common/AgentsStarter.cpp +0 -2
- data/ext/common/AgentsStarter.h +0 -1
- data/ext/common/AgentsStarter.hpp +1 -3
- data/ext/common/ApplicationPool2/AppTypes.cpp +74 -0
- data/ext/common/ApplicationPool2/AppTypes.h +202 -0
- data/ext/common/ApplicationPool2/Common.h +12 -10
- data/ext/common/ApplicationPool2/DirectSpawner.h +256 -0
- data/ext/common/ApplicationPool2/DummySpawner.h +90 -0
- data/ext/common/ApplicationPool2/Group.h +311 -94
- data/ext/common/ApplicationPool2/Implementation.cpp +405 -145
- data/ext/common/ApplicationPool2/Options.h +24 -26
- data/ext/common/ApplicationPool2/PipeWatcher.h +20 -13
- data/ext/common/ApplicationPool2/Pool.h +326 -183
- data/ext/common/ApplicationPool2/Process.h +205 -55
- data/ext/common/ApplicationPool2/README.md +1 -1
- data/ext/common/ApplicationPool2/Session.h +21 -10
- data/ext/common/ApplicationPool2/SmartSpawner.h +801 -0
- data/ext/common/ApplicationPool2/Spawner.h +141 -1149
- data/ext/common/ApplicationPool2/SpawnerFactory.h +132 -0
- data/ext/common/ApplicationPool2/SuperGroup.h +146 -223
- data/ext/common/Constants.h +4 -2
- data/ext/common/Exceptions.h +23 -1
- data/ext/common/Logging.cpp +17 -6
- data/ext/common/Logging.h +37 -7
- data/ext/common/ResourceLocator.h +1 -1
- data/ext/common/Utils.cpp +49 -1
- data/ext/common/Utils.h +13 -4
- data/ext/common/{AnsiColorConstants.h → Utils/AnsiColorConstants.h} +0 -0
- data/ext/common/{BCrypt.cpp → Utils/BCrypt.cpp} +0 -0
- data/ext/common/{BCrypt.h → Utils/BCrypt.h} +0 -0
- data/ext/common/{Blowfish.c → Utils/Blowfish.c} +0 -0
- data/ext/common/{Blowfish.h → Utils/Blowfish.h} +0 -0
- data/ext/common/Utils/CachedFileStat.hpp +27 -25
- data/ext/common/Utils/Curl.h +184 -0
- data/ext/common/{HttpConstants.h → Utils/HttpConstants.h} +3 -0
- data/ext/common/Utils/IOUtils.cpp +6 -2
- data/ext/common/{IniFile.h → Utils/IniFile.h} +0 -0
- data/ext/common/Utils/LargeFiles.cpp +30 -0
- data/ext/common/Utils/LargeFiles.h +40 -0
- data/ext/common/Utils/StrIntUtils.cpp +72 -8
- data/ext/common/Utils/StrIntUtils.h +24 -2
- data/ext/common/Utils/StringMap.h +12 -2
- data/ext/common/Utils/VariantMap.h +51 -2
- data/ext/common/Utils/jsoncpp.cpp +1 -1
- data/ext/common/agents/Base.cpp +147 -11
- data/ext/common/agents/HelperAgent/AgentOptions.h +14 -6
- data/ext/common/agents/HelperAgent/Main.cpp +79 -19
- data/ext/common/agents/HelperAgent/RequestHandler.h +36 -16
- data/ext/common/agents/LoggingAgent/LoggingServer.h +3 -5
- data/ext/common/agents/LoggingAgent/Main.cpp +2 -4
- data/ext/common/agents/LoggingAgent/RemoteSender.h +18 -24
- data/ext/common/agents/SpawnPreparer.cpp +7 -0
- data/ext/common/agents/Watchdog/Main.cpp +96 -38
- data/ext/nginx/Configuration.c +26 -22
- data/ext/nginx/Configuration.h +4 -2
- data/ext/nginx/ContentHandler.c +23 -52
- data/ext/nginx/ContentHandler.h +5 -11
- data/ext/nginx/config +10 -3
- data/ext/nginx/ngx_http_passenger_module.c +21 -6
- data/ext/nginx/ngx_http_passenger_module.h +4 -1
- data/ext/oxt/dynamic_thread_group.hpp +9 -1
- data/ext/oxt/system_calls.cpp +2 -2
- data/ext/ruby/extconf.rb +2 -1
- data/helper-scripts/backtrace-sanitizer.rb +2 -0
- data/helper-scripts/wsgi-loader.py +54 -21
- data/lib/phusion_passenger.rb +5 -3
- data/lib/phusion_passenger/abstract_installer.rb +18 -41
- data/lib/phusion_passenger/admin_tools/memory_stats.rb +2 -2
- data/lib/phusion_passenger/admin_tools/server_instance.rb +2 -2
- data/lib/phusion_passenger/common_library.rb +23 -3
- data/lib/phusion_passenger/debug_logging.rb +10 -3
- data/lib/phusion_passenger/packaging.rb +1 -0
- data/lib/phusion_passenger/platform_info.rb +113 -115
- data/lib/phusion_passenger/platform_info/compiler.rb +224 -134
- data/lib/phusion_passenger/platform_info/cxx_portability.rb +143 -0
- data/lib/phusion_passenger/platform_info/depcheck.rb +371 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +124 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +97 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +39 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +118 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +137 -0
- data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +15 -0
- data/lib/phusion_passenger/platform_info/operating_system.rb +6 -5
- data/lib/phusion_passenger/platform_info/ruby.rb +45 -34
- data/lib/phusion_passenger/request_handler.rb +35 -22
- data/lib/phusion_passenger/request_handler/thread_handler.rb +5 -6
- data/lib/phusion_passenger/ruby_core_enhancements.rb +7 -1
- data/lib/phusion_passenger/standalone/runtime_installer.rb +43 -34
- data/lib/phusion_passenger/utils/robust_interruption.rb +34 -18
- data/passenger.gemspec +25 -0
- data/resources/templates/standalone/config.erb +3 -1
- data/test/config.json.travis +2 -2
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +37 -5
- data/test/cxx/ApplicationPool2/PoolTest.cpp +143 -50
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +8 -0
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +28 -17
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +31 -26
- data/test/cxx/RequestHandlerTest.cpp +17 -1
- data/test/cxx/UtilsTest.cpp +84 -10
- data/test/integration_tests/apache2_tests.rb +49 -163
- data/test/integration_tests/hello_world_wsgi_spec.rb +2 -2
- data/test/integration_tests/mycook_spec.rb +1 -1
- data/test/integration_tests/nginx_tests.rb +37 -19
- data/test/ruby/request_handler_spec.rb +1 -0
- data/test/ruby/spec_helper.rb +52 -1
- data/test/stub/nginx/nginx.conf.erb +2 -0
- data/test/stub/rack/start.rb +5 -0
- data/test/stub/rails3.0/Gemfile.lock +30 -30
- data/test/stub/rails3.1/Gemfile +1 -1
- data/test/stub/rails3.1/Gemfile.lock +3 -3
- data/test/stub/rails3.2/Gemfile +1 -1
- data/test/stub/rails3.2/Gemfile.lock +4 -4
- data/test/stub/rails_apps/2.3/mycook/app/controllers/welcome_controller.rb +1 -1
- data/test/stub/rails_apps/2.3/mycook/app/helpers/recipes_helper.rb +2 -0
- data/test/stub/rails_apps/2.3/mycook/app/helpers/test_helper.rb +2 -0
- data/test/stub/rails_apps/2.3/mycook/app/helpers/uploads_helper.rb +2 -0
- data/test/stub/rails_apps/2.3/mycook/app/helpers/welcome_helper.rb +2 -0
- data/test/support/nginx_controller.rb +2 -1
- metadata +160 -156
- data/build/gempackagetask.rb +0 -99
- data/build/packagetask.rb +0 -186
- data/ext/common/StringListCreator.h +0 -83
- data/lib/phusion_passenger/dependencies.rb +0 -657
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011
|
3
|
+
* Copyright (c) 2011-2013 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -29,6 +29,7 @@
|
|
29
29
|
#include <list>
|
30
30
|
#include <boost/shared_ptr.hpp>
|
31
31
|
#include <boost/make_shared.hpp>
|
32
|
+
#include <oxt/system_calls.hpp>
|
32
33
|
#include <oxt/macros.hpp>
|
33
34
|
#include <sys/types.h>
|
34
35
|
#include <cstdio>
|
@@ -92,29 +93,48 @@ public:
|
|
92
93
|
* The admin socket, an anonymous Unix domain socket, is mapped to the process's
|
93
94
|
* STDIN and STDOUT and has two functions.
|
94
95
|
*
|
95
|
-
*
|
96
|
-
*
|
97
|
-
*
|
98
|
-
*
|
96
|
+
* 1. It acts as the main communication channel with the process. Commands are
|
97
|
+
* sent to and responses are received from it.
|
98
|
+
* 2. It's used for garbage collection: closing the STDIN part causes the process
|
99
|
+
* to gracefully terminate itself.
|
99
100
|
*
|
100
101
|
* Except for the otherwise documented parts, this class is not thread-safe,
|
101
102
|
* so only use within the Pool lock.
|
102
103
|
*
|
103
|
-
*
|
104
|
+
* ## Normal usage
|
104
105
|
*
|
105
|
-
*
|
106
|
-
*
|
107
|
-
*
|
108
|
-
*
|
109
|
-
*
|
106
|
+
* 1. Create a session with newSession().
|
107
|
+
* 2. Initiate the session by calling initiate() on it.
|
108
|
+
* 3. Perform I/O through session->fd().
|
109
|
+
* 4. When done, close the session by calling close() on it.
|
110
|
+
* 5. Call process.sessionClosed().
|
111
|
+
*
|
112
|
+
* ## Life time
|
113
|
+
*
|
114
|
+
* A Process object lives until the containing Group calls `detach(process)`,
|
115
|
+
* which indicates that it wants this Process to should down. This causes
|
116
|
+
* the Process to enter the `detached() == true` state. Processes in this
|
117
|
+
* state are stored in the `detachedProcesses` collection in the Group and
|
118
|
+
* are no longer eligible for receiving requests. They will be removed from
|
119
|
+
* the Group and destroyed when all of the following applies:
|
120
|
+
*
|
121
|
+
* 1. the OS process is gone.
|
122
|
+
* 2. `sessions == 0`
|
123
|
+
*
|
124
|
+
* This means that a Group outlives all its Processes, a Process outlives all
|
125
|
+
* its Sessions, and a Process also outlives the OS process.
|
110
126
|
*/
|
111
127
|
class Process: public enable_shared_from_this<Process> {
|
112
128
|
private:
|
113
129
|
friend class Group;
|
114
130
|
|
115
|
-
/** A mutex to protect access to
|
116
|
-
mutable boost::mutex
|
117
|
-
|
131
|
+
/** A mutex to protect access to `m_shutDown`. */
|
132
|
+
mutable boost::mutex lifetimeSyncher;
|
133
|
+
|
134
|
+
/** Group inside the Pool that this Process belongs to.
|
135
|
+
* Should never be NULL because a Group should outlive all of its Processes.
|
136
|
+
* Read-only; only set once during initialization.
|
137
|
+
*/
|
118
138
|
weak_ptr<Group> group;
|
119
139
|
|
120
140
|
/** A subset of 'sockets': all sockets that speak the
|
@@ -125,7 +145,7 @@ private:
|
|
125
145
|
ProcessList::iterator it;
|
126
146
|
/** The handle inside the associated Group's process priority queue. */
|
127
147
|
PriorityQueue<Process>::Handle pqHandle;
|
128
|
-
|
148
|
+
|
129
149
|
void indexSessionSockets() {
|
130
150
|
SocketList::iterator it;
|
131
151
|
concurrency = 0;
|
@@ -165,8 +185,6 @@ public:
|
|
165
185
|
string connectPassword;
|
166
186
|
/** Admin socket, see class description. */
|
167
187
|
FileDescriptor adminSocket;
|
168
|
-
PipeWatcherPtr adminSocketWatcher;
|
169
|
-
PipeWatcherPtr errorPipeWatcher;
|
170
188
|
/** The sockets that this Process listens on for connections. */
|
171
189
|
SocketListPtr sockets;
|
172
190
|
/** Time at which the Spawner that created this process was created.
|
@@ -177,6 +195,16 @@ public:
|
|
177
195
|
/** The maximum amount of concurrent sessions this process can handle.
|
178
196
|
* 0 means unlimited. */
|
179
197
|
int concurrency;
|
198
|
+
/** If true, then indicates that this Process does not refer to a real OS
|
199
|
+
* process. The sockets in the socket list are fake and need not be deleted,
|
200
|
+
* the admin socket need not be closed, etc.
|
201
|
+
*/
|
202
|
+
bool dummy;
|
203
|
+
/** Whether it is required that shutdown() must be called before destroying
|
204
|
+
* this Process. Normally true, except for dummy Process objects created by
|
205
|
+
* Pool::asyncGet() with options.noop == true.
|
206
|
+
*/
|
207
|
+
bool requiresShutdown;
|
180
208
|
|
181
209
|
/*************************************************************
|
182
210
|
* Information used by Pool. Do not write to these from
|
@@ -196,17 +224,42 @@ public:
|
|
196
224
|
int sessions;
|
197
225
|
/** Number of sessions opened so far. */
|
198
226
|
unsigned int processed;
|
227
|
+
/** Do not access directly, always use `isAlive()`/`isShutDown()`/`getLifeStatus()` or
|
228
|
+
* through `lifetimeSyncher`. */
|
229
|
+
enum LifeStatus {
|
230
|
+
/** Up and operational. */
|
231
|
+
ALIVE,
|
232
|
+
/** Being shut down. The containing Group has just detached this
|
233
|
+
* Process and is now waiting for it to be shutdownable.
|
234
|
+
*/
|
235
|
+
SHUTTING_DOWN,
|
236
|
+
/**
|
237
|
+
* Shut down. Object no longer usable. No more sessions are active.
|
238
|
+
*/
|
239
|
+
SHUT_DOWN
|
240
|
+
} lifeStatus;
|
199
241
|
enum EnabledStatus {
|
242
|
+
/** Up and operational. */
|
200
243
|
ENABLED,
|
244
|
+
/** Process is being disabled. The containing Group is waiting for
|
245
|
+
* all sessions on this Process to finish. It may in some corner
|
246
|
+
* cases still be selected for processing requests.
|
247
|
+
*/
|
201
248
|
DISABLING,
|
249
|
+
/** Process is fully disabled and should not be handling any
|
250
|
+
* requests. It *may* still handle some requests, e.g. by
|
251
|
+
* the Out-of-Band-Work trigger.
|
252
|
+
*/
|
202
253
|
DISABLED
|
203
254
|
} enabled;
|
204
|
-
ProcessMetrics metrics;
|
205
|
-
|
206
255
|
/** Marks whether the process requested out-of-band work. If so, we need to
|
207
256
|
* wait until all sessions have ended and the process has been disabled.
|
208
257
|
*/
|
209
258
|
bool oobwRequested;
|
259
|
+
/** Caches whether or not the OS process still exists. */
|
260
|
+
mutable bool m_osProcessExists;
|
261
|
+
/** Collected by Pool::collectAnalytics(). */
|
262
|
+
ProcessMetrics metrics;
|
210
263
|
|
211
264
|
Process(const SafeLibevPtr _libev,
|
212
265
|
pid_t _pid,
|
@@ -231,10 +284,15 @@ public:
|
|
231
284
|
sockets(_sockets),
|
232
285
|
spawnerCreationTime(_spawnerCreationTime),
|
233
286
|
spawnStartTime(_spawnStartTime),
|
287
|
+
concurrency(0),
|
288
|
+
dummy(false),
|
289
|
+
requiresShutdown(true),
|
234
290
|
sessions(0),
|
235
291
|
processed(0),
|
292
|
+
lifeStatus(ALIVE),
|
236
293
|
enabled(ENABLED),
|
237
|
-
oobwRequested(false)
|
294
|
+
oobwRequested(false),
|
295
|
+
m_osProcessExists(true)
|
238
296
|
{
|
239
297
|
SpawnerConfigPtr config;
|
240
298
|
if (_config == NULL) {
|
@@ -243,17 +301,17 @@ public:
|
|
243
301
|
config = _config;
|
244
302
|
}
|
245
303
|
|
246
|
-
if (
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
304
|
+
if (_adminSocket != -1) {
|
305
|
+
PipeWatcherPtr watcher = make_shared<PipeWatcher>(_adminSocket,
|
306
|
+
"stdout", pid, config->forwardStdout);
|
307
|
+
watcher->initialize();
|
308
|
+
watcher->start();
|
251
309
|
}
|
252
|
-
if (
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
310
|
+
if (_errorPipe != -1) {
|
311
|
+
PipeWatcherPtr watcher = make_shared<PipeWatcher>(_errorPipe,
|
312
|
+
"stderr", pid, config->forwardStderr);
|
313
|
+
watcher->initialize();
|
314
|
+
watcher->start();
|
257
315
|
}
|
258
316
|
|
259
317
|
if (OXT_LIKELY(sockets != NULL)) {
|
@@ -265,39 +323,118 @@ public:
|
|
265
323
|
}
|
266
324
|
|
267
325
|
~Process() {
|
268
|
-
if (
|
269
|
-
|
270
|
-
|
271
|
-
if (getSocketAddressType(it->address) == SAT_UNIX) {
|
272
|
-
string filename = parseUnixSocketAddress(it->address);
|
273
|
-
syscalls::unlink(filename.c_str());
|
274
|
-
}
|
275
|
-
}
|
326
|
+
if (OXT_UNLIKELY(!isShutDown() && requiresShutdown)) {
|
327
|
+
P_BUG("You must call Process::shutdown() before actually "
|
328
|
+
"destroying the Process object.");
|
276
329
|
}
|
277
|
-
// The admin socket stays alive for a while thanks to adminSocketWatcher,
|
278
|
-
// so we shutdown the writable part to close the child's stdin.
|
279
|
-
syscalls::shutdown(adminSocket, SHUT_WR);
|
280
330
|
}
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
331
|
+
|
332
|
+
static void maybeShutdown(ProcessPtr process) {
|
333
|
+
if (process != NULL) {
|
334
|
+
process->shutdown();
|
335
|
+
}
|
336
|
+
}
|
337
|
+
|
338
|
+
/**
|
339
|
+
* Thread-safe.
|
340
|
+
* @pre getLifeState() != SHUT_DOWN
|
341
|
+
* @post result != NULL
|
342
|
+
*/
|
343
|
+
const GroupPtr getGroup() const {
|
344
|
+
assert(!isShutDown());
|
285
345
|
return group.lock();
|
286
346
|
}
|
287
347
|
|
288
|
-
// Thread-safe.
|
289
348
|
void setGroup(const GroupPtr &group) {
|
290
|
-
|
349
|
+
assert(this->group.lock() == NULL || this->group.lock() == group);
|
291
350
|
this->group = group;
|
292
351
|
}
|
293
|
-
|
352
|
+
|
353
|
+
/**
|
354
|
+
* Thread-safe.
|
355
|
+
* @pre getLifeState() != SHUT_DOWN
|
356
|
+
* @post result != NULL
|
357
|
+
*/
|
358
|
+
SuperGroupPtr getSuperGroup() const;
|
359
|
+
|
294
360
|
// Thread-safe.
|
295
|
-
bool
|
296
|
-
|
361
|
+
bool isAlive() const {
|
362
|
+
lock_guard<boost::mutex> lock(lifetimeSyncher);
|
363
|
+
return lifeStatus == ALIVE;
|
297
364
|
}
|
298
365
|
|
299
|
-
// Thread-safe
|
300
|
-
|
366
|
+
// Thread-safe.
|
367
|
+
bool isShutDown() const {
|
368
|
+
lock_guard<boost::mutex> lock(lifetimeSyncher);
|
369
|
+
return lifeStatus == SHUT_DOWN;
|
370
|
+
}
|
371
|
+
|
372
|
+
// Thread-safe.
|
373
|
+
LifeStatus getLifeStatus() const {
|
374
|
+
lock_guard<boost::mutex> lock(lifetimeSyncher);
|
375
|
+
return lifeStatus;
|
376
|
+
}
|
377
|
+
|
378
|
+
void setShuttingDown() {
|
379
|
+
{
|
380
|
+
lock_guard<boost::mutex> lock(lifetimeSyncher);
|
381
|
+
assert(lifeStatus == ALIVE);
|
382
|
+
lifeStatus = SHUTTING_DOWN;
|
383
|
+
}
|
384
|
+
if (!dummy) {
|
385
|
+
syscalls::shutdown(adminSocket, SHUT_WR);
|
386
|
+
}
|
387
|
+
}
|
388
|
+
|
389
|
+
void shutdown() {
|
390
|
+
LifeStatus ls = getLifeStatus();
|
391
|
+
if (ls == SHUT_DOWN || !requiresShutdown) {
|
392
|
+
// Some code have guards that call process->shutdown().
|
393
|
+
// Returning instead of enforcing !isShutdown() makes things easier.
|
394
|
+
return;
|
395
|
+
}
|
396
|
+
|
397
|
+
assert(sessions == 0);
|
398
|
+
|
399
|
+
if (ls == ALIVE) {
|
400
|
+
setShuttingDown();
|
401
|
+
}
|
402
|
+
|
403
|
+
P_TRACE(2, "Shutting down Process object " << inspect());
|
404
|
+
if (!dummy) {
|
405
|
+
if (OXT_LIKELY(sockets != NULL)) {
|
406
|
+
SocketList::const_iterator it, end = sockets->end();
|
407
|
+
for (it = sockets->begin(); it != end; it++) {
|
408
|
+
if (getSocketAddressType(it->address) == SAT_UNIX) {
|
409
|
+
string filename = parseUnixSocketAddress(it->address);
|
410
|
+
syscalls::unlink(filename.c_str());
|
411
|
+
}
|
412
|
+
}
|
413
|
+
}
|
414
|
+
}
|
415
|
+
|
416
|
+
lock_guard<boost::mutex> lock(lifetimeSyncher);
|
417
|
+
lifeStatus = SHUT_DOWN;
|
418
|
+
}
|
419
|
+
|
420
|
+
bool canBeShutDown() const {
|
421
|
+
return sessions == 0 && !osProcessExists();
|
422
|
+
}
|
423
|
+
|
424
|
+
/** Checks whether the OS process exists.
|
425
|
+
* Once it has been detected that it doesn't, that event is remembered
|
426
|
+
* so that we don't accidentally ping any new processes that have the
|
427
|
+
* same PID.
|
428
|
+
*/
|
429
|
+
bool osProcessExists() const {
|
430
|
+
if (!dummy && m_osProcessExists) {
|
431
|
+
// Once we detect that a process is gone.
|
432
|
+
m_osProcessExists = syscalls::kill(pid, 0) == 0 || errno != ESRCH;
|
433
|
+
return m_osProcessExists;
|
434
|
+
} else {
|
435
|
+
return false;
|
436
|
+
}
|
437
|
+
}
|
301
438
|
|
302
439
|
int utilization() const {
|
303
440
|
/* Different processes within a Group may have different
|
@@ -320,6 +457,7 @@ public:
|
|
320
457
|
}
|
321
458
|
}
|
322
459
|
|
460
|
+
// TODO: remove this
|
323
461
|
bool atFullCapacity() const {
|
324
462
|
return atFullUtilization();
|
325
463
|
}
|
@@ -360,7 +498,7 @@ public:
|
|
360
498
|
socket->sessions--;
|
361
499
|
this->sessions--;
|
362
500
|
sessionSockets.decrease(socket->pqHandle, socket->utilization());
|
363
|
-
assert(!
|
501
|
+
assert(!atFullUtilization());
|
364
502
|
}
|
365
503
|
|
366
504
|
/**
|
@@ -386,6 +524,19 @@ public:
|
|
386
524
|
stream << "<spawn_end_time>" << spawnEndTime << "</spawn_end_time>";
|
387
525
|
stream << "<last_used>" << lastUsed << "</last_used>";
|
388
526
|
stream << "<uptime>" << uptime() << "</uptime>";
|
527
|
+
switch (lifeStatus) {
|
528
|
+
case ALIVE:
|
529
|
+
stream << "<life_status>alive</life_status>";
|
530
|
+
break;
|
531
|
+
case SHUTTING_DOWN:
|
532
|
+
stream << "<life_status>shutting_down</life_status>";
|
533
|
+
break;
|
534
|
+
case SHUT_DOWN:
|
535
|
+
stream << "<life_status>shut_down</life_status>";
|
536
|
+
break;
|
537
|
+
default:
|
538
|
+
P_BUG("Unknown 'lifeStatus' state " << (int) lifeStatus);
|
539
|
+
}
|
389
540
|
switch (enabled) {
|
390
541
|
case ENABLED:
|
391
542
|
stream << "<enabled>enabled</enabled>";
|
@@ -397,8 +548,7 @@ public:
|
|
397
548
|
stream << "<enabled>disabled</enabled>";
|
398
549
|
break;
|
399
550
|
default:
|
400
|
-
|
401
|
-
break;
|
551
|
+
P_BUG("Unknown 'enabled' state " << (int) enabled);
|
402
552
|
}
|
403
553
|
if (includeSockets) {
|
404
554
|
SocketList::const_iterator it;
|
@@ -76,7 +76,7 @@ carefully.
|
|
76
76
|
exceptions are Spawner methods which are explicitly documented as not
|
77
77
|
depending on the event loop.
|
78
78
|
|
79
|
-
Pool must only
|
79
|
+
Pool must only call Spawner methods from background threads. There's still a
|
80
80
|
caveat though: Pool's destructor waits for all background threads to finish.
|
81
81
|
Therefore one must not destroy Pool from the event loop. Instead, I recommend
|
82
82
|
running the event loop in a separate thread, destroy Pool from the main
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011
|
3
|
+
* Copyright (c) 2011-2013 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -54,7 +54,6 @@ public:
|
|
54
54
|
typedef void (*Callback)(Session *session);
|
55
55
|
|
56
56
|
private:
|
57
|
-
/** For keeping the OS process alive until all of a Process's sessions are closed. */
|
58
57
|
ProcessPtr process;
|
59
58
|
/** Socket to use for this session. Guaranteed to be alive thanks to the 'process' reference. */
|
60
59
|
Socket *socket;
|
@@ -87,13 +86,13 @@ public:
|
|
87
86
|
Callback onInitiateFailure;
|
88
87
|
Callback onClose;
|
89
88
|
|
90
|
-
Session(const ProcessPtr &
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
89
|
+
Session(const ProcessPtr &_process, Socket *_socket)
|
90
|
+
: process(_process),
|
91
|
+
socket(_socket),
|
92
|
+
closed(false),
|
93
|
+
onInitiateFailure(NULL),
|
94
|
+
onClose(NULL)
|
95
|
+
{ }
|
97
96
|
|
98
97
|
~Session() {
|
99
98
|
TRACE_POINT();
|
@@ -105,14 +104,23 @@ public:
|
|
105
104
|
callOnClose();
|
106
105
|
}
|
107
106
|
}
|
108
|
-
|
107
|
+
|
109
108
|
const string &getConnectPassword() const;
|
110
109
|
pid_t getPid() const;
|
111
110
|
const string &getGupid() const;
|
112
111
|
const GroupPtr getGroup() const;
|
113
112
|
void requestOOBW();
|
114
113
|
|
114
|
+
bool isClosed() const {
|
115
|
+
return closed;
|
116
|
+
}
|
117
|
+
|
118
|
+
/**
|
119
|
+
* @pre !isClosed()
|
120
|
+
* @post result != NULL
|
121
|
+
*/
|
115
122
|
const ProcessPtr &getProcess() const {
|
123
|
+
assert(!closed);
|
116
124
|
return process;
|
117
125
|
}
|
118
126
|
|
@@ -141,6 +149,9 @@ public:
|
|
141
149
|
return theFd;
|
142
150
|
}
|
143
151
|
|
152
|
+
/**
|
153
|
+
* This Session object becomes fully unsable after closing.
|
154
|
+
*/
|
144
155
|
void close(bool success) {
|
145
156
|
if (OXT_LIKELY(initiated())) {
|
146
157
|
deinitiate(success);
|