passenger 5.0.9 → 5.0.10
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/CHANGELOG +15 -0
- data/CONTRIBUTORS +6 -0
- data/README.md +1 -1
- data/bin/passenger-install-apache2-module +24 -11
- data/bin/passenger-status +29 -14
- data/build/agents.rb +12 -10
- data/build/cxx_tests.rb +30 -30
- data/doc/Design and Architecture.html +1 -10
- data/doc/Design and Architecture.txt +1 -6
- data/doc/Users guide Apache.html +1 -19
- data/doc/Users guide Apache.txt +1 -1
- data/doc/Users guide Nginx.html +2 -20
- data/doc/Users guide Nginx.txt +2 -2
- data/doc/users_guide_snippets/tips.txt +0 -9
- data/ext/common/ApplicationPool2/ApiKey.h +158 -0
- data/ext/common/ApplicationPool2/BasicGroupInfo.h +81 -0
- data/ext/common/ApplicationPool2/BasicProcessInfo.h +106 -0
- data/ext/common/ApplicationPool2/Common.h +5 -44
- data/ext/common/ApplicationPool2/Context.h +94 -0
- data/ext/common/ApplicationPool2/Group.h +130 -1205
- data/ext/common/ApplicationPool2/Group/InitializationAndShutdown.cpp +190 -0
- data/ext/common/ApplicationPool2/Group/InternalUtils.cpp +329 -0
- data/ext/common/ApplicationPool2/Group/LifetimeAndBasics.cpp +103 -0
- data/ext/common/ApplicationPool2/{Pool/Debug.h → Group/Miscellaneous.cpp} +40 -38
- data/ext/common/ApplicationPool2/Group/OutOfBandWork.cpp +323 -0
- data/ext/common/ApplicationPool2/Group/ProcessListManagement.cpp +606 -0
- data/ext/common/ApplicationPool2/Group/SessionManagement.cpp +337 -0
- data/ext/common/ApplicationPool2/Group/SpawningAndRestarting.cpp +478 -0
- data/ext/common/ApplicationPool2/Group/StateInspection.cpp +197 -0
- data/ext/common/ApplicationPool2/Group/Verification.cpp +159 -0
- data/ext/common/ApplicationPool2/Implementation.cpp +19 -1401
- data/ext/common/ApplicationPool2/Options.h +5 -5
- data/ext/common/ApplicationPool2/Pool.h +260 -815
- data/ext/common/ApplicationPool2/Pool/{AnalyticsCollection.h → AnalyticsCollection.cpp} +55 -56
- data/ext/common/ApplicationPool2/Pool/{GarbageCollection.h → GarbageCollection.cpp} +49 -49
- data/ext/common/ApplicationPool2/Pool/GeneralUtils.cpp +241 -0
- data/ext/common/ApplicationPool2/Pool/GroupUtils.cpp +276 -0
- data/ext/common/ApplicationPool2/Pool/InitializationAndShutdown.cpp +145 -0
- data/ext/common/ApplicationPool2/Pool/Miscellaneous.cpp +244 -0
- data/ext/common/ApplicationPool2/Pool/ProcessUtils.cpp +330 -0
- data/ext/common/ApplicationPool2/Pool/StateInspection.cpp +299 -0
- data/ext/common/ApplicationPool2/Process.h +399 -205
- data/ext/common/ApplicationPool2/Session.h +70 -28
- data/ext/common/ApplicationPool2/Socket.h +1 -0
- data/ext/common/Constants.h +11 -3
- data/ext/common/Exceptions.h +1 -1
- data/ext/common/Logging.cpp +9 -4
- data/ext/common/Logging.h +6 -0
- data/ext/common/ServerKit/HttpServer.h +225 -215
- data/ext/common/ServerKit/Server.h +57 -57
- data/ext/common/SpawningKit/BackgroundIOCapturer.h +160 -0
- data/ext/common/SpawningKit/Config.h +107 -0
- data/ext/common/{ApplicationPool2 → SpawningKit}/DirectSpawner.h +17 -16
- data/ext/common/{ApplicationPool2 → SpawningKit}/DummySpawner.h +33 -33
- data/ext/common/{ApplicationPool2/SpawnerFactory.h → SpawningKit/Factory.h} +17 -17
- data/ext/common/{ApplicationPool2/ComponentInfo.h → SpawningKit/Options.h} +8 -21
- data/ext/common/SpawningKit/PipeWatcher.h +148 -0
- data/ext/common/{ApplicationPool2/PipeWatcher.h → SpawningKit/Result.h} +15 -33
- data/ext/common/{ApplicationPool2 → SpawningKit}/SmartSpawner.h +52 -57
- data/ext/common/{ApplicationPool2 → SpawningKit}/Spawner.h +83 -371
- data/ext/common/SpawningKit/UserSwitchingRules.h +265 -0
- data/ext/common/Utils/BufferedIO.h +24 -0
- data/ext/common/{ApplicationPool2/SpawnObject.h → Utils/ClassUtils.h} +24 -51
- data/ext/common/Utils/IOUtils.cpp +70 -0
- data/ext/common/Utils/IOUtils.h +19 -0
- data/ext/common/Utils/JsonUtils.h +113 -0
- data/ext/common/Utils/StrIntUtils.h +29 -0
- data/ext/common/Utils/json.h +1 -1
- data/ext/common/agents/ApiServerUtils.h +941 -0
- data/ext/common/agents/HelperAgent/{AdminServer.h → ApiServer.h} +163 -365
- data/ext/common/agents/HelperAgent/Main.cpp +86 -88
- data/ext/common/agents/HelperAgent/OptionParser.h +9 -10
- data/ext/common/agents/HelperAgent/RequestHandler/BufferBody.cpp +3 -0
- data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +2 -0
- data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +1 -1
- data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +2 -2
- data/ext/common/agents/LoggingAgent/ApiServer.h +279 -0
- data/ext/common/agents/LoggingAgent/Main.cpp +41 -51
- data/ext/common/agents/LoggingAgent/OptionParser.h +11 -11
- data/ext/common/agents/Watchdog/ApiServer.h +311 -0
- data/ext/common/agents/Watchdog/Main.cpp +91 -65
- data/helper-scripts/prespawn +2 -0
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/admin_tools/instance.rb +1 -1
- data/lib/phusion_passenger/common_library.rb +27 -14
- data/lib/phusion_passenger/config/{admin_command_command.rb → api_call_command.rb} +19 -16
- data/lib/phusion_passenger/config/detach_process_command.rb +6 -3
- data/lib/phusion_passenger/config/main.rb +3 -5
- data/lib/phusion_passenger/config/reopen_logs_command.rb +29 -7
- data/lib/phusion_passenger/config/restart_app_command.rb +13 -4
- data/lib/phusion_passenger/config/utils.rb +15 -8
- data/lib/phusion_passenger/constants.rb +6 -2
- data/lib/phusion_passenger/platform_info/apache.rb +4 -0
- data/lib/phusion_passenger/platform_info/apache_detector.rb +18 -3
- data/resources/templates/apache2/mpm_unknown.txt.erb +20 -0
- metadata +42 -21
- metadata.gz.asc +7 -7
- data/ext/common/ApplicationPool2/Pool/GeneralUtils.h +0 -127
- data/ext/common/ApplicationPool2/Pool/Inspection.h +0 -219
- data/ext/common/ApplicationPool2/Pool/ProcessUtils.h +0 -85
- data/ext/common/ApplicationPool2/SuperGroup.h +0 -706
- data/ext/common/agents/LoggingAgent/AdminServer.h +0 -435
- data/ext/common/agents/Watchdog/AdminServer.h +0 -432
@@ -0,0 +1,103 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2011-2015 Phusion
|
4
|
+
*
|
5
|
+
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
|
+
*
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
12
|
+
* furnished to do so, subject to the following conditions:
|
13
|
+
*
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
15
|
+
* all copies or substantial portions of the Software.
|
16
|
+
*
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
* THE SOFTWARE.
|
24
|
+
*/
|
25
|
+
#include <ApplicationPool2/Group.h>
|
26
|
+
|
27
|
+
/*************************************************************************
|
28
|
+
*
|
29
|
+
* Functions for ApplicationPool2::Group for handling life time, basic info,
|
30
|
+
* backreferences and related objects
|
31
|
+
*
|
32
|
+
*************************************************************************/
|
33
|
+
|
34
|
+
namespace Passenger {
|
35
|
+
namespace ApplicationPool2 {
|
36
|
+
|
37
|
+
using namespace std;
|
38
|
+
using namespace boost;
|
39
|
+
|
40
|
+
|
41
|
+
/****************************
|
42
|
+
*
|
43
|
+
* Public methods
|
44
|
+
*
|
45
|
+
****************************/
|
46
|
+
|
47
|
+
|
48
|
+
// Thread-safe.
|
49
|
+
bool
|
50
|
+
Group::isAlive() const {
|
51
|
+
return getLifeStatus() == ALIVE;
|
52
|
+
}
|
53
|
+
|
54
|
+
// Thread-safe.
|
55
|
+
OXT_FORCE_INLINE
|
56
|
+
Group::LifeStatus
|
57
|
+
Group::getLifeStatus() const {
|
58
|
+
return (LifeStatus) lifeStatus.load(boost::memory_order_acquire);
|
59
|
+
}
|
60
|
+
|
61
|
+
StaticString
|
62
|
+
Group::getName() const {
|
63
|
+
return info.name;
|
64
|
+
}
|
65
|
+
|
66
|
+
const BasicGroupInfo &
|
67
|
+
Group::getInfo() {
|
68
|
+
return info;
|
69
|
+
}
|
70
|
+
|
71
|
+
const ApiKey &
|
72
|
+
Group::getApiKey() const {
|
73
|
+
return info.apiKey;
|
74
|
+
}
|
75
|
+
|
76
|
+
/**
|
77
|
+
* Thread-safe.
|
78
|
+
* @pre getLifeState() != SHUT_DOWN
|
79
|
+
* @post result != NULL
|
80
|
+
*/
|
81
|
+
OXT_FORCE_INLINE Pool *
|
82
|
+
Group::getPool() const {
|
83
|
+
return pool;
|
84
|
+
}
|
85
|
+
|
86
|
+
Context *
|
87
|
+
Group::getContext() const {
|
88
|
+
return info.context;
|
89
|
+
}
|
90
|
+
|
91
|
+
psg_pool_t *
|
92
|
+
Group::getPallocPool() const {
|
93
|
+
return getPool()->palloc;
|
94
|
+
}
|
95
|
+
|
96
|
+
const ResourceLocator &
|
97
|
+
Group::getResourceLocator() const {
|
98
|
+
return *getPool()->getSpawningKitConfig()->resourceLocator;
|
99
|
+
}
|
100
|
+
|
101
|
+
|
102
|
+
} // namespace ApplicationPool2
|
103
|
+
} // namespace Passenger
|
@@ -22,42 +22,44 @@
|
|
22
22
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
23
|
* THE SOFTWARE.
|
24
24
|
*/
|
25
|
+
#include <ApplicationPool2/Group.h>
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
27
|
+
/*************************************************************************
|
28
|
+
*
|
29
|
+
* Miscellaneous for ApplicationPool2::Group
|
30
|
+
*
|
31
|
+
*************************************************************************/
|
32
|
+
|
33
|
+
namespace Passenger {
|
34
|
+
namespace ApplicationPool2 {
|
35
|
+
|
36
|
+
using namespace std;
|
37
|
+
using namespace boost;
|
38
|
+
|
39
|
+
|
40
|
+
/****************************
|
41
|
+
*
|
42
|
+
* Public methods
|
43
|
+
*
|
44
|
+
****************************/
|
45
|
+
|
46
|
+
|
47
|
+
void
|
48
|
+
Group::cleanupSpawner(boost::container::vector<Callback> &postLockActions) {
|
49
|
+
assert(isAlive());
|
50
|
+
postLockActions.push_back(boost::bind(doCleanupSpawner, spawner));
|
51
|
+
}
|
52
|
+
|
53
|
+
bool
|
54
|
+
Group::authorizeByUid(uid_t uid) const {
|
55
|
+
return uid == 0 || SpawningKit::prepareUserSwitching(options).uid == uid;
|
56
|
+
}
|
57
|
+
|
58
|
+
bool
|
59
|
+
Group::authorizeByApiKey(const ApiKey &key) const {
|
60
|
+
return key.isSuper() || key == getApiKey();
|
61
|
+
}
|
62
|
+
|
63
|
+
|
64
|
+
} // namespace ApplicationPool2
|
65
|
+
} // namespace Passenger
|
@@ -0,0 +1,323 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2011-2015 Phusion
|
4
|
+
*
|
5
|
+
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
|
+
*
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
12
|
+
* furnished to do so, subject to the following conditions:
|
13
|
+
*
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
15
|
+
* all copies or substantial portions of the Software.
|
16
|
+
*
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
* THE SOFTWARE.
|
24
|
+
*/
|
25
|
+
#include <ApplicationPool2/Group.h>
|
26
|
+
#include <MessageReadersWriters.h>
|
27
|
+
|
28
|
+
/*************************************************************************
|
29
|
+
*
|
30
|
+
* Out-of-band work functions for ApplicationPool2::Group
|
31
|
+
*
|
32
|
+
*************************************************************************/
|
33
|
+
|
34
|
+
namespace Passenger {
|
35
|
+
namespace ApplicationPool2 {
|
36
|
+
|
37
|
+
using namespace std;
|
38
|
+
using namespace boost;
|
39
|
+
|
40
|
+
|
41
|
+
/****************************
|
42
|
+
*
|
43
|
+
* Private methods
|
44
|
+
*
|
45
|
+
****************************/
|
46
|
+
|
47
|
+
|
48
|
+
/** Returns whether it is allowed to perform a new OOBW in this group. */
|
49
|
+
bool
|
50
|
+
Group::oobwAllowed() const {
|
51
|
+
unsigned int oobwInstances = 0;
|
52
|
+
foreach (const ProcessPtr &process, disablingProcesses) {
|
53
|
+
if (process->oobwStatus == Process::OOBW_IN_PROGRESS) {
|
54
|
+
oobwInstances += 1;
|
55
|
+
}
|
56
|
+
}
|
57
|
+
foreach (const ProcessPtr &process, disabledProcesses) {
|
58
|
+
if (process->oobwStatus == Process::OOBW_IN_PROGRESS) {
|
59
|
+
oobwInstances += 1;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
return oobwInstances < options.maxOutOfBandWorkInstances;
|
63
|
+
}
|
64
|
+
|
65
|
+
/** Returns whether a new OOBW should be initiated for this process. */
|
66
|
+
bool
|
67
|
+
Group::shouldInitiateOobw(Process *process) const {
|
68
|
+
return process->oobwStatus == Process::OOBW_REQUESTED
|
69
|
+
&& process->enabled != Process::DETACHED
|
70
|
+
&& process->isAlive()
|
71
|
+
&& oobwAllowed();
|
72
|
+
}
|
73
|
+
|
74
|
+
void
|
75
|
+
Group::maybeInitiateOobw(Process *process) {
|
76
|
+
if (shouldInitiateOobw(process)) {
|
77
|
+
// We keep an extra reference to prevent premature destruction.
|
78
|
+
ProcessPtr p = process->shared_from_this();
|
79
|
+
initiateOobw(p);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
// The 'self' parameter is for keeping the current Group object alive
|
84
|
+
void
|
85
|
+
Group::lockAndMaybeInitiateOobw(const ProcessPtr &process, DisableResult result, GroupPtr self) {
|
86
|
+
TRACE_POINT();
|
87
|
+
|
88
|
+
// Standard resource management boilerplate stuff...
|
89
|
+
Pool *pool = getPool();
|
90
|
+
boost::unique_lock<boost::mutex> lock(pool->syncher);
|
91
|
+
if (OXT_UNLIKELY(!process->isAlive() || !isAlive())) {
|
92
|
+
return;
|
93
|
+
}
|
94
|
+
|
95
|
+
assert(process->oobwStatus == Process::OOBW_IN_PROGRESS);
|
96
|
+
|
97
|
+
if (result == DR_SUCCESS) {
|
98
|
+
if (process->enabled == Process::DISABLED) {
|
99
|
+
P_DEBUG("Process " << process->inspect() << " disabled; proceeding " <<
|
100
|
+
"with out-of-band work");
|
101
|
+
process->oobwStatus = Process::OOBW_REQUESTED;
|
102
|
+
if (shouldInitiateOobw(process.get())) {
|
103
|
+
initiateOobw(process);
|
104
|
+
} else {
|
105
|
+
// We do not re-enable the process because it's likely that the
|
106
|
+
// administrator has explicitly changed the state.
|
107
|
+
P_DEBUG("Out-of-band work for process " << process->inspect() << " aborted "
|
108
|
+
"because the process no longer requests out-of-band work");
|
109
|
+
process->oobwStatus = Process::OOBW_NOT_ACTIVE;
|
110
|
+
}
|
111
|
+
} else {
|
112
|
+
// We do not re-enable the process because it's likely that the
|
113
|
+
// administrator has explicitly changed the state.
|
114
|
+
P_DEBUG("Out-of-band work for process " << process->inspect() << " aborted "
|
115
|
+
"because the process was reenabled after disabling");
|
116
|
+
process->oobwStatus = Process::OOBW_NOT_ACTIVE;
|
117
|
+
}
|
118
|
+
} else {
|
119
|
+
P_DEBUG("Out-of-band work for process " << process->inspect() << " aborted "
|
120
|
+
"because the process could not be disabled");
|
121
|
+
process->oobwStatus = Process::OOBW_NOT_ACTIVE;
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
void
|
126
|
+
Group::initiateOobw(const ProcessPtr &process) {
|
127
|
+
assert(process->oobwStatus == Process::OOBW_REQUESTED);
|
128
|
+
|
129
|
+
process->oobwStatus = Process::OOBW_IN_PROGRESS;
|
130
|
+
|
131
|
+
if (process->enabled == Process::ENABLED
|
132
|
+
|| process->enabled == Process::DISABLING)
|
133
|
+
{
|
134
|
+
// We want the process to be disabled. However, disabling a process is potentially
|
135
|
+
// asynchronous, so we pass a callback which will re-aquire the lock and call this
|
136
|
+
// method again.
|
137
|
+
P_DEBUG("Disabling process " << process->inspect() << " in preparation for OOBW");
|
138
|
+
DisableResult result = disable(process,
|
139
|
+
boost::bind(&Group::lockAndMaybeInitiateOobw, this,
|
140
|
+
_1, _2, shared_from_this()));
|
141
|
+
switch (result) {
|
142
|
+
case DR_SUCCESS:
|
143
|
+
// Continue code flow.
|
144
|
+
break;
|
145
|
+
case DR_DEFERRED:
|
146
|
+
// lockAndMaybeInitiateOobw() will eventually be called.
|
147
|
+
return;
|
148
|
+
case DR_ERROR:
|
149
|
+
case DR_NOOP:
|
150
|
+
P_DEBUG("Out-of-band work for process " << process->inspect() << " aborted "
|
151
|
+
"because the process could not be disabled");
|
152
|
+
process->oobwStatus = Process::OOBW_NOT_ACTIVE;
|
153
|
+
return;
|
154
|
+
default:
|
155
|
+
P_BUG("Unexpected disable() result " << result);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
assert(process->enabled == Process::DISABLED);
|
160
|
+
assert(process->sessions == 0);
|
161
|
+
|
162
|
+
P_DEBUG("Initiating OOBW request for process " << process->inspect());
|
163
|
+
interruptableThreads.create_thread(
|
164
|
+
boost::bind(&Group::spawnThreadOOBWRequest, this, shared_from_this(), process),
|
165
|
+
"OOBW request thread for process " + process->inspect(),
|
166
|
+
POOL_HELPER_THREAD_STACK_SIZE);
|
167
|
+
}
|
168
|
+
|
169
|
+
// The 'self' parameter is for keeping the current Group object alive while this thread is running.
|
170
|
+
void
|
171
|
+
Group::spawnThreadOOBWRequest(GroupPtr self, ProcessPtr process) {
|
172
|
+
TRACE_POINT();
|
173
|
+
this_thread::disable_interruption di;
|
174
|
+
this_thread::disable_syscall_interruption dsi;
|
175
|
+
|
176
|
+
Socket *socket;
|
177
|
+
Connection connection;
|
178
|
+
Pool *pool = getPool();
|
179
|
+
Pool::DebugSupportPtr debug = pool->debugSupport;
|
180
|
+
|
181
|
+
UPDATE_TRACE_POINT();
|
182
|
+
P_DEBUG("Performing OOBW request for process " << process->inspect());
|
183
|
+
if (debug != NULL && debug->oobw) {
|
184
|
+
debug->debugger->send("OOBW request about to start");
|
185
|
+
debug->messages->recv("Proceed with OOBW request");
|
186
|
+
}
|
187
|
+
|
188
|
+
UPDATE_TRACE_POINT();
|
189
|
+
{
|
190
|
+
// Standard resource management boilerplate stuff...
|
191
|
+
boost::unique_lock<boost::mutex> lock(pool->syncher);
|
192
|
+
if (OXT_UNLIKELY(!process->isAlive()
|
193
|
+
|| process->enabled == Process::DETACHED
|
194
|
+
|| !isAlive()))
|
195
|
+
{
|
196
|
+
return;
|
197
|
+
}
|
198
|
+
|
199
|
+
if (process->enabled != Process::DISABLED) {
|
200
|
+
UPDATE_TRACE_POINT();
|
201
|
+
P_INFO("Out-of-Band Work canceled: process " << process->inspect() <<
|
202
|
+
" was concurrently re-enabled.");
|
203
|
+
if (debug != NULL && debug->oobw) {
|
204
|
+
debug->debugger->send("OOBW request canceled");
|
205
|
+
}
|
206
|
+
return;
|
207
|
+
}
|
208
|
+
|
209
|
+
assert(process->oobwStatus == Process::OOBW_IN_PROGRESS);
|
210
|
+
assert(process->sessions == 0);
|
211
|
+
socket = process->findSessionSocketWithLowestBusyness();
|
212
|
+
}
|
213
|
+
|
214
|
+
UPDATE_TRACE_POINT();
|
215
|
+
unsigned long long timeout = 1000 * 1000 * 60; // 1 min
|
216
|
+
try {
|
217
|
+
this_thread::restore_interruption ri(di);
|
218
|
+
this_thread::restore_syscall_interruption rsi(dsi);
|
219
|
+
|
220
|
+
// Grab a connection. The connection is marked as fail in order to
|
221
|
+
// ensure it is closed / recycled after this request (otherwise we'd
|
222
|
+
// need to completely read the response).
|
223
|
+
connection = socket->checkoutConnection();
|
224
|
+
connection.fail = true;
|
225
|
+
ScopeGuard guard(boost::bind(&Socket::checkinConnection, socket, connection));
|
226
|
+
|
227
|
+
// This is copied from RequestHandler when it is sending data using the
|
228
|
+
// "session" protocol.
|
229
|
+
char sizeField[sizeof(boost::uint32_t)];
|
230
|
+
SmallVector<StaticString, 10> data;
|
231
|
+
|
232
|
+
data.push_back(StaticString(sizeField, sizeof(boost::uint32_t)));
|
233
|
+
data.push_back(P_STATIC_STRING_WITH_NULL("REQUEST_METHOD"));
|
234
|
+
data.push_back(P_STATIC_STRING_WITH_NULL("OOBW"));
|
235
|
+
|
236
|
+
data.push_back(P_STATIC_STRING_WITH_NULL("PASSENGER_CONNECT_PASSWORD"));
|
237
|
+
data.push_back(getApiKey().toStaticString());
|
238
|
+
data.push_back(StaticString("", 1));
|
239
|
+
|
240
|
+
boost::uint32_t dataSize = 0;
|
241
|
+
for (unsigned int i = 1; i < data.size(); i++) {
|
242
|
+
dataSize += (boost::uint32_t) data[i].size();
|
243
|
+
}
|
244
|
+
Uint32Message::generate(sizeField, dataSize);
|
245
|
+
|
246
|
+
gatheredWrite(connection.fd, &data[0], data.size(), &timeout);
|
247
|
+
|
248
|
+
// We do not care what the actual response is ... just wait for it.
|
249
|
+
UPDATE_TRACE_POINT();
|
250
|
+
waitUntilReadable(connection.fd, &timeout);
|
251
|
+
} catch (const SystemException &e) {
|
252
|
+
P_ERROR("*** ERROR: " << e.what() << "\n" << e.backtrace());
|
253
|
+
} catch (const TimeoutException &e) {
|
254
|
+
P_ERROR("*** ERROR: " << e.what() << "\n" << e.backtrace());
|
255
|
+
}
|
256
|
+
|
257
|
+
UPDATE_TRACE_POINT();
|
258
|
+
boost::container::vector<Callback> actions;
|
259
|
+
{
|
260
|
+
// Standard resource management boilerplate stuff...
|
261
|
+
Pool *pool = getPool();
|
262
|
+
boost::unique_lock<boost::mutex> lock(pool->syncher);
|
263
|
+
if (OXT_UNLIKELY(!process->isAlive() || !isAlive())) {
|
264
|
+
return;
|
265
|
+
}
|
266
|
+
|
267
|
+
process->oobwStatus = Process::OOBW_NOT_ACTIVE;
|
268
|
+
if (process->enabled == Process::DISABLED) {
|
269
|
+
enable(process, actions);
|
270
|
+
assignSessionsToGetWaiters(actions);
|
271
|
+
}
|
272
|
+
|
273
|
+
pool->fullVerifyInvariants();
|
274
|
+
|
275
|
+
initiateNextOobwRequest();
|
276
|
+
}
|
277
|
+
UPDATE_TRACE_POINT();
|
278
|
+
runAllActions(actions);
|
279
|
+
actions.clear();
|
280
|
+
|
281
|
+
UPDATE_TRACE_POINT();
|
282
|
+
P_DEBUG("Finished OOBW request for process " << process->inspect());
|
283
|
+
if (debug != NULL && debug->oobw) {
|
284
|
+
debug->debugger->send("OOBW request finished");
|
285
|
+
}
|
286
|
+
}
|
287
|
+
|
288
|
+
void
|
289
|
+
Group::initiateNextOobwRequest() {
|
290
|
+
ProcessList::const_iterator it, end = enabledProcesses.end();
|
291
|
+
for (it = enabledProcesses.begin(); it != end; it++) {
|
292
|
+
const ProcessPtr &process = *it;
|
293
|
+
if (shouldInitiateOobw(process.get())) {
|
294
|
+
// We keep an extra reference to processes to prevent premature destruction.
|
295
|
+
ProcessPtr p = process;
|
296
|
+
initiateOobw(p);
|
297
|
+
return;
|
298
|
+
}
|
299
|
+
}
|
300
|
+
}
|
301
|
+
|
302
|
+
|
303
|
+
/****************************
|
304
|
+
*
|
305
|
+
* Public methods
|
306
|
+
*
|
307
|
+
****************************/
|
308
|
+
|
309
|
+
|
310
|
+
// Thread-safe, but only call outside the pool lock!
|
311
|
+
void
|
312
|
+
Group::requestOOBW(const ProcessPtr &process) {
|
313
|
+
// Standard resource management boilerplate stuff...
|
314
|
+
Pool *pool = getPool();
|
315
|
+
boost::unique_lock<boost::mutex> lock(pool->syncher);
|
316
|
+
if (isAlive() && process->isAlive() && process->oobwStatus == Process::OOBW_NOT_ACTIVE) {
|
317
|
+
process->oobwStatus = Process::OOBW_REQUESTED;
|
318
|
+
}
|
319
|
+
}
|
320
|
+
|
321
|
+
|
322
|
+
} // namespace ApplicationPool2
|
323
|
+
} // namespace Passenger
|