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.

Files changed (106) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/CHANGELOG +15 -0
  5. data/CONTRIBUTORS +6 -0
  6. data/README.md +1 -1
  7. data/bin/passenger-install-apache2-module +24 -11
  8. data/bin/passenger-status +29 -14
  9. data/build/agents.rb +12 -10
  10. data/build/cxx_tests.rb +30 -30
  11. data/doc/Design and Architecture.html +1 -10
  12. data/doc/Design and Architecture.txt +1 -6
  13. data/doc/Users guide Apache.html +1 -19
  14. data/doc/Users guide Apache.txt +1 -1
  15. data/doc/Users guide Nginx.html +2 -20
  16. data/doc/Users guide Nginx.txt +2 -2
  17. data/doc/users_guide_snippets/tips.txt +0 -9
  18. data/ext/common/ApplicationPool2/ApiKey.h +158 -0
  19. data/ext/common/ApplicationPool2/BasicGroupInfo.h +81 -0
  20. data/ext/common/ApplicationPool2/BasicProcessInfo.h +106 -0
  21. data/ext/common/ApplicationPool2/Common.h +5 -44
  22. data/ext/common/ApplicationPool2/Context.h +94 -0
  23. data/ext/common/ApplicationPool2/Group.h +130 -1205
  24. data/ext/common/ApplicationPool2/Group/InitializationAndShutdown.cpp +190 -0
  25. data/ext/common/ApplicationPool2/Group/InternalUtils.cpp +329 -0
  26. data/ext/common/ApplicationPool2/Group/LifetimeAndBasics.cpp +103 -0
  27. data/ext/common/ApplicationPool2/{Pool/Debug.h → Group/Miscellaneous.cpp} +40 -38
  28. data/ext/common/ApplicationPool2/Group/OutOfBandWork.cpp +323 -0
  29. data/ext/common/ApplicationPool2/Group/ProcessListManagement.cpp +606 -0
  30. data/ext/common/ApplicationPool2/Group/SessionManagement.cpp +337 -0
  31. data/ext/common/ApplicationPool2/Group/SpawningAndRestarting.cpp +478 -0
  32. data/ext/common/ApplicationPool2/Group/StateInspection.cpp +197 -0
  33. data/ext/common/ApplicationPool2/Group/Verification.cpp +159 -0
  34. data/ext/common/ApplicationPool2/Implementation.cpp +19 -1401
  35. data/ext/common/ApplicationPool2/Options.h +5 -5
  36. data/ext/common/ApplicationPool2/Pool.h +260 -815
  37. data/ext/common/ApplicationPool2/Pool/{AnalyticsCollection.h → AnalyticsCollection.cpp} +55 -56
  38. data/ext/common/ApplicationPool2/Pool/{GarbageCollection.h → GarbageCollection.cpp} +49 -49
  39. data/ext/common/ApplicationPool2/Pool/GeneralUtils.cpp +241 -0
  40. data/ext/common/ApplicationPool2/Pool/GroupUtils.cpp +276 -0
  41. data/ext/common/ApplicationPool2/Pool/InitializationAndShutdown.cpp +145 -0
  42. data/ext/common/ApplicationPool2/Pool/Miscellaneous.cpp +244 -0
  43. data/ext/common/ApplicationPool2/Pool/ProcessUtils.cpp +330 -0
  44. data/ext/common/ApplicationPool2/Pool/StateInspection.cpp +299 -0
  45. data/ext/common/ApplicationPool2/Process.h +399 -205
  46. data/ext/common/ApplicationPool2/Session.h +70 -28
  47. data/ext/common/ApplicationPool2/Socket.h +1 -0
  48. data/ext/common/Constants.h +11 -3
  49. data/ext/common/Exceptions.h +1 -1
  50. data/ext/common/Logging.cpp +9 -4
  51. data/ext/common/Logging.h +6 -0
  52. data/ext/common/ServerKit/HttpServer.h +225 -215
  53. data/ext/common/ServerKit/Server.h +57 -57
  54. data/ext/common/SpawningKit/BackgroundIOCapturer.h +160 -0
  55. data/ext/common/SpawningKit/Config.h +107 -0
  56. data/ext/common/{ApplicationPool2 → SpawningKit}/DirectSpawner.h +17 -16
  57. data/ext/common/{ApplicationPool2 → SpawningKit}/DummySpawner.h +33 -33
  58. data/ext/common/{ApplicationPool2/SpawnerFactory.h → SpawningKit/Factory.h} +17 -17
  59. data/ext/common/{ApplicationPool2/ComponentInfo.h → SpawningKit/Options.h} +8 -21
  60. data/ext/common/SpawningKit/PipeWatcher.h +148 -0
  61. data/ext/common/{ApplicationPool2/PipeWatcher.h → SpawningKit/Result.h} +15 -33
  62. data/ext/common/{ApplicationPool2 → SpawningKit}/SmartSpawner.h +52 -57
  63. data/ext/common/{ApplicationPool2 → SpawningKit}/Spawner.h +83 -371
  64. data/ext/common/SpawningKit/UserSwitchingRules.h +265 -0
  65. data/ext/common/Utils/BufferedIO.h +24 -0
  66. data/ext/common/{ApplicationPool2/SpawnObject.h → Utils/ClassUtils.h} +24 -51
  67. data/ext/common/Utils/IOUtils.cpp +70 -0
  68. data/ext/common/Utils/IOUtils.h +19 -0
  69. data/ext/common/Utils/JsonUtils.h +113 -0
  70. data/ext/common/Utils/StrIntUtils.h +29 -0
  71. data/ext/common/Utils/json.h +1 -1
  72. data/ext/common/agents/ApiServerUtils.h +941 -0
  73. data/ext/common/agents/HelperAgent/{AdminServer.h → ApiServer.h} +163 -365
  74. data/ext/common/agents/HelperAgent/Main.cpp +86 -88
  75. data/ext/common/agents/HelperAgent/OptionParser.h +9 -10
  76. data/ext/common/agents/HelperAgent/RequestHandler/BufferBody.cpp +3 -0
  77. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +2 -0
  78. data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +1 -1
  79. data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +2 -2
  80. data/ext/common/agents/LoggingAgent/ApiServer.h +279 -0
  81. data/ext/common/agents/LoggingAgent/Main.cpp +41 -51
  82. data/ext/common/agents/LoggingAgent/OptionParser.h +11 -11
  83. data/ext/common/agents/Watchdog/ApiServer.h +311 -0
  84. data/ext/common/agents/Watchdog/Main.cpp +91 -65
  85. data/helper-scripts/prespawn +2 -0
  86. data/lib/phusion_passenger.rb +1 -1
  87. data/lib/phusion_passenger/admin_tools/instance.rb +1 -1
  88. data/lib/phusion_passenger/common_library.rb +27 -14
  89. data/lib/phusion_passenger/config/{admin_command_command.rb → api_call_command.rb} +19 -16
  90. data/lib/phusion_passenger/config/detach_process_command.rb +6 -3
  91. data/lib/phusion_passenger/config/main.rb +3 -5
  92. data/lib/phusion_passenger/config/reopen_logs_command.rb +29 -7
  93. data/lib/phusion_passenger/config/restart_app_command.rb +13 -4
  94. data/lib/phusion_passenger/config/utils.rb +15 -8
  95. data/lib/phusion_passenger/constants.rb +6 -2
  96. data/lib/phusion_passenger/platform_info/apache.rb +4 -0
  97. data/lib/phusion_passenger/platform_info/apache_detector.rb +18 -3
  98. data/resources/templates/apache2/mpm_unknown.txt.erb +20 -0
  99. metadata +42 -21
  100. metadata.gz.asc +7 -7
  101. data/ext/common/ApplicationPool2/Pool/GeneralUtils.h +0 -127
  102. data/ext/common/ApplicationPool2/Pool/Inspection.h +0 -219
  103. data/ext/common/ApplicationPool2/Pool/ProcessUtils.h +0 -85
  104. data/ext/common/ApplicationPool2/SuperGroup.h +0 -706
  105. data/ext/common/agents/LoggingAgent/AdminServer.h +0 -435
  106. 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
- // This file is included inside the Pool class.
27
-
28
- protected:
29
-
30
- struct DebugSupport {
31
- /** Mailbox for the unit tests to receive messages on. */
32
- MessageBoxPtr debugger;
33
- /** Mailbox for the ApplicationPool code to receive messages on. */
34
- MessageBoxPtr messages;
35
-
36
- // Choose aspects to debug.
37
- bool restarting;
38
- bool spawning;
39
- bool superGroup;
40
- bool oobw;
41
- bool testOverflowRequestQueue;
42
- bool detachedProcessesChecker;
43
-
44
- // The following fields may only be accessed by Pool.
45
- boost::mutex syncher;
46
- unsigned int spawnLoopIteration;
47
-
48
- DebugSupport() {
49
- debugger = boost::make_shared<MessageBox>();
50
- messages = boost::make_shared<MessageBox>();
51
- restarting = true;
52
- spawning = true;
53
- superGroup = false;
54
- oobw = false;
55
- detachedProcessesChecker = false;
56
- testOverflowRequestQueue = false;
57
- spawnLoopIteration = 0;
58
- }
59
- };
60
-
61
- typedef boost::shared_ptr<DebugSupport> DebugSupportPtr;
62
-
63
- DebugSupportPtr debugSupport;
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