passenger 5.0.26 → 5.0.27
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 +4 -4
- data/CHANGELOG +17 -0
- data/CONTRIBUTORS +1 -0
- data/build/cxx_dependency_map.rb +113 -157
- data/build/cxx_tests.rb +8 -1
- data/src/agent/Core/ApplicationPool/TestSession.h +5 -1
- data/src/agent/Core/Controller/CheckoutSession.cpp +1 -1
- data/src/agent/Core/Controller/ForwardResponse.cpp +9 -0
- data/src/agent/Core/Controller/InternalUtils.cpp +9 -1
- data/src/agent/Core/Controller/SendRequest.cpp +13 -7
- data/src/agent/Core/Controller/StateInspectionAndConfiguration.cpp +3 -2
- data/src/agent/Core/CoreMain.cpp +3 -0
- data/src/agent/Core/SpawningKit/SmartSpawner.h +1 -1
- data/src/agent/Core/SpawningKit/Spawner.h +2 -2
- data/src/agent/Core/UnionStation/StopwatchLog.h +3 -4
- data/src/agent/Shared/Base.cpp +32 -0
- data/src/agent/Shared/Base.h +2 -0
- data/src/agent/UstRouter/UstRouterMain.cpp +3 -0
- data/src/agent/Watchdog/AgentWatcher.cpp +1 -3
- data/src/agent/Watchdog/WatchdogMain.cpp +31 -6
- data/src/apache2_module/Hooks.cpp +2 -2
- data/src/cxx_supportlib/BackgroundEventLoop.cpp +12 -2
- data/src/cxx_supportlib/Constants.h +1 -1
- data/src/cxx_supportlib/DataStructures/LString.cpp +39 -0
- data/src/cxx_supportlib/DataStructures/LString.h +35 -6
- data/src/cxx_supportlib/FileDescriptor.h +3 -1
- data/src/cxx_supportlib/Integrations/LibevJsonUtils.h +92 -0
- data/src/cxx_supportlib/ResourceLocator.h +10 -8
- data/src/cxx_supportlib/ServerKit/CookieUtils.h +4 -0
- data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +2 -0
- data/src/cxx_supportlib/ServerKit/HttpServer.h +6 -2
- data/src/cxx_supportlib/Utils.cpp +4 -5
- data/src/cxx_supportlib/Utils.h +2 -2
- data/src/cxx_supportlib/Utils/IOUtils.cpp +1 -1
- data/src/cxx_supportlib/Utils/JsonUtils.h +12 -10
- data/src/cxx_supportlib/Utils/MessagePassing.h +4 -4
- data/src/cxx_supportlib/Utils/StrIntUtils.cpp +7 -3
- data/src/cxx_supportlib/Utils/SystemTime.cpp +15 -4
- data/src/cxx_supportlib/Utils/SystemTime.h +228 -54
- data/src/cxx_supportlib/Utils/Timer.h +14 -41
- data/src/cxx_supportlib/WatchdogLauncher.h +1 -1
- data/src/cxx_supportlib/vendor-copy/libuv/Makefile.in +198 -59
- data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/output.0 +15477 -0
- data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/output.1 +15477 -0
- data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/requests +324 -0
- data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/traces.0 +3105 -0
- data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/traces.1 +703 -0
- data/src/cxx_supportlib/vendor-copy/libuv/configure +115 -12
- data/src/cxx_supportlib/vendor-copy/libuv/ltmain.sh +15 -8
- data/src/cxx_supportlib/vendor-copy/libuv/m4/ltversion.m4 +5 -5
- data/src/cxx_supportlib/vendor-modified/psg_sysqueue.h +1 -0
- data/src/nginx_module/ngx_http_passenger_module.c +1 -1
- data/src/nodejs_supportlib/phusion_passenger/ustreporter.js +1 -1
- data/src/ruby_native_extension/passenger_native_support.c +1 -1
- data/src/ruby_supportlib/phusion_passenger.rb +15 -1
- data/src/ruby_supportlib/phusion_passenger/common_library.rb +4 -0
- data/src/ruby_supportlib/phusion_passenger/packaging.rb +1 -0
- data/src/ruby_supportlib/phusion_passenger/ruby_core_io_enhancements.rb +5 -20
- metadata +9 -2
data/build/cxx_tests.rb
CHANGED
@@ -198,7 +198,14 @@ task 'test:cxx' => dependencies do
|
|
198
198
|
if boolean_option('GDB')
|
199
199
|
command = "gdb --args #{command}"
|
200
200
|
elsif boolean_option('VALGRIND')
|
201
|
-
|
201
|
+
valgrind_args = "--dsymutil=yes --vgdb=yes --vgdb-error=1 --child-silent-after-fork=yes"
|
202
|
+
if boolean_option('LEAK_CHECK')
|
203
|
+
valgrind_args << " --leak-check=yes"
|
204
|
+
end
|
205
|
+
if RUBY_PLATFORM =~ /darwin/
|
206
|
+
valgrind_args << " --suppressions=valgrind-osx.supp"
|
207
|
+
end
|
208
|
+
command = "valgrind #{valgrind_args} #{command}"
|
202
209
|
end
|
203
210
|
if boolean_option('SUDO')
|
204
211
|
command = "#{PlatformInfo.ruby_sudo_command} #{command}"
|
@@ -38,7 +38,11 @@ namespace ApplicationPool2 {
|
|
38
38
|
|
39
39
|
using namespace std;
|
40
40
|
|
41
|
-
|
41
|
+
/**
|
42
|
+
* The TestSession represents a session between the Core to the Application. There is a
|
43
|
+
* connection between the two, which is represented by a SocketPair having a first (Core side)
|
44
|
+
* and second (Application side) FD. These are also referred to as fd and peerFd.
|
45
|
+
*/
|
42
46
|
class TestSession: public AbstractSession {
|
43
47
|
private:
|
44
48
|
mutable boost::mutex syncher;
|
@@ -64,7 +64,7 @@ Controller::checkoutSession(Client *client, Request *req) {
|
|
64
64
|
callback.func = sessionCheckedOut;
|
65
65
|
callback.userData = req;
|
66
66
|
|
67
|
-
options.currentTime = (
|
67
|
+
options.currentTime = SystemTime::getUsec();
|
68
68
|
|
69
69
|
refRequest(req, __FILE__, __LINE__);
|
70
70
|
#ifdef DEBUG_CC_EVENT_LOOP_BLOCKING
|
@@ -822,6 +822,7 @@ Controller::sendResponseHeaderWithWritev(Client *client, Request *req,
|
|
822
822
|
if (constructHeaderBuffersForResponse(req, buffers,
|
823
823
|
maxbuffers, nbuffers, dataSize, nCacheableBuffers))
|
824
824
|
{
|
825
|
+
UPDATE_TRACE_POINT();
|
825
826
|
SKC_TRACE(client, 2, "Sending response headers using writev()");
|
826
827
|
logResponseHeaders(client, req, buffers, nbuffers, dataSize);
|
827
828
|
markHeaderBuffersForTurboCaching(client, req, buffers, nCacheableBuffers);
|
@@ -834,6 +835,7 @@ Controller::sendResponseHeaderWithWritev(Client *client, Request *req,
|
|
834
835
|
req->responseBegun |= ret > 0;
|
835
836
|
return ret == (ssize_t) dataSize;
|
836
837
|
} else {
|
838
|
+
UPDATE_TRACE_POINT();
|
837
839
|
bytesWritten = 0;
|
838
840
|
return false;
|
839
841
|
}
|
@@ -843,6 +845,7 @@ void
|
|
843
845
|
Controller::sendResponseHeaderWithBuffering(Client *client, Request *req,
|
844
846
|
unsigned int offset)
|
845
847
|
{
|
848
|
+
TRACE_POINT();
|
846
849
|
struct iovec *buffers;
|
847
850
|
unsigned int nbuffers, dataSize, nCacheableBuffers;
|
848
851
|
bool ok;
|
@@ -858,18 +861,21 @@ Controller::sendResponseHeaderWithBuffering(Client *client, Request *req,
|
|
858
861
|
assert(ok);
|
859
862
|
(void) ok; // Shut up compiler warning
|
860
863
|
|
864
|
+
UPDATE_TRACE_POINT();
|
861
865
|
logResponseHeaders(client, req, buffers, nbuffers, dataSize);
|
862
866
|
markHeaderBuffersForTurboCaching(client, req, buffers, nCacheableBuffers);
|
863
867
|
|
864
868
|
MemoryKit::mbuf_pool &mbuf_pool = getContext()->mbuf_pool;
|
865
869
|
const unsigned int MBUF_MAX_SIZE = mbuf_pool_data_size(&mbuf_pool);
|
866
870
|
if (dataSize <= MBUF_MAX_SIZE) {
|
871
|
+
UPDATE_TRACE_POINT();
|
867
872
|
SKC_TRACE(client, 2, "Sending response headers using an mbuf");
|
868
873
|
MemoryKit::mbuf buffer(MemoryKit::mbuf_get(&mbuf_pool));
|
869
874
|
gatherBuffers(buffer.start, MBUF_MAX_SIZE, buffers, nbuffers);
|
870
875
|
buffer = MemoryKit::mbuf(buffer, offset, dataSize - offset);
|
871
876
|
writeResponse(client, buffer);
|
872
877
|
} else {
|
878
|
+
UPDATE_TRACE_POINT();
|
873
879
|
SKC_TRACE(client, 2, "Sending response headers using a psg_pool buffer");
|
874
880
|
char *buffer = (char *) psg_pnalloc(req->pool, dataSize);
|
875
881
|
gatherBuffers(buffer, dataSize, buffers, nbuffers);
|
@@ -882,6 +888,7 @@ Controller::logResponseHeaders(Client *client, Request *req, struct iovec *buffe
|
|
882
888
|
unsigned int nbuffers, unsigned int dataSize)
|
883
889
|
{
|
884
890
|
if (OXT_UNLIKELY(getLogLevel() >= LVL_DEBUG3)) {
|
891
|
+
TRACE_POINT();
|
885
892
|
char *buffer = (char *) psg_pnalloc(req->pool, dataSize);
|
886
893
|
gatherBuffers(buffer, dataSize, buffers, nbuffers);
|
887
894
|
SKC_TRACE(client, 3, "Sending response headers: \"" <<
|
@@ -889,6 +896,7 @@ Controller::logResponseHeaders(Client *client, Request *req, struct iovec *buffe
|
|
889
896
|
}
|
890
897
|
|
891
898
|
if (req->useUnionStation()) {
|
899
|
+
TRACE_POINT();
|
892
900
|
const char *status = getStatusCodeAndReasonPhrase(req->appResponse.statusCode);
|
893
901
|
if (status != NULL) {
|
894
902
|
req->logMessage("Status: " + StaticString(status));
|
@@ -899,6 +907,7 @@ Controller::logResponseHeaders(Client *client, Request *req, struct iovec *buffe
|
|
899
907
|
if (req->appResponse.statusCode >= 400 && req->appResponse.statusCode <= 599) {
|
900
908
|
// Log the request headers like Request headers: { header1: values1-concatenated, header2: values2-concatenated } (single line)
|
901
909
|
// Concatenation was already done by HeaderTable.h:insert (using a comma ',' for joining, or a semicolon ';' for Cookie headers
|
910
|
+
UPDATE_TRACE_POINT();
|
902
911
|
ServerKit::HeaderTable::Iterator it(req->headers);
|
903
912
|
Json::Value json;
|
904
913
|
while (*it != NULL) {
|
@@ -102,7 +102,15 @@ Controller::disconnectWithAppSocketWriteError(Client **client, int e) {
|
|
102
102
|
void
|
103
103
|
Controller::endRequestWithAppSocketIncompleteResponse(Client **client, Request **req) {
|
104
104
|
if (!(*req)->responseBegun) {
|
105
|
-
|
105
|
+
// The application might have decided to abort the response because it thinks the client
|
106
|
+
// is already gone (Passenger relays socket half-close events from clients), so don't
|
107
|
+
// make a big warning out of that situation.
|
108
|
+
if ((*req)->halfClosePolicy == Request::HALF_CLOSE_PERFORMED) {
|
109
|
+
SKC_DEBUG(*client, "Sending 502 response: application did not send a complete response"
|
110
|
+
" (likely because client half-closed)");
|
111
|
+
} else {
|
112
|
+
SKC_WARN(*client, "Sending 502 response: application did not send a complete response");
|
113
|
+
}
|
106
114
|
endRequestWithSimpleResponse(client, req,
|
107
115
|
"<h2>Incomplete response received from application</h2>", 502);
|
108
116
|
} else {
|
@@ -24,9 +24,7 @@
|
|
24
24
|
* THE SOFTWARE.
|
25
25
|
*/
|
26
26
|
#include <Core/Controller.h>
|
27
|
-
|
28
|
-
// For calculating delta_monotonic (Ruby < 2.1 workaround, otherwise unused)
|
29
|
-
#include <uv.h>
|
27
|
+
#include <Utils/SystemTime.h>
|
30
28
|
|
31
29
|
/*************************************************************************
|
32
30
|
*
|
@@ -159,10 +157,18 @@ Controller::sendHeaderToAppWithSessionProtocol(Client *client, Request *req) {
|
|
159
157
|
SessionProtocolWorkingState state;
|
160
158
|
|
161
159
|
// Workaround for Ruby < 2.1 support.
|
162
|
-
std::string
|
160
|
+
std::string deltaMonotonic;
|
161
|
+
unsigned long long now = SystemTime::getUsec();
|
162
|
+
MonotonicTimeUsec monotonicNow = SystemTime::getMonotonicUsec();
|
163
|
+
if (now > monotonicNow) {
|
164
|
+
deltaMonotonic = boost::to_string(now - monotonicNow);
|
165
|
+
} else {
|
166
|
+
long long diff = monotonicNow - now;
|
167
|
+
deltaMonotonic = boost::to_string(-diff);
|
168
|
+
}
|
163
169
|
|
164
170
|
unsigned int bufferSize = determineHeaderSizeForSessionProtocol(req,
|
165
|
-
state,
|
171
|
+
state, deltaMonotonic);
|
166
172
|
MemoryKit::mbuf_pool &mbuf_pool = getContext()->mbuf_pool;
|
167
173
|
const unsigned int MBUF_MAX_SIZE = mbuf_pool_data_size(&mbuf_pool);
|
168
174
|
bool ok;
|
@@ -172,7 +178,7 @@ Controller::sendHeaderToAppWithSessionProtocol(Client *client, Request *req) {
|
|
172
178
|
bufferSize = MBUF_MAX_SIZE;
|
173
179
|
|
174
180
|
ok = constructHeaderForSessionProtocol(req, buffer.start,
|
175
|
-
bufferSize, state,
|
181
|
+
bufferSize, state, deltaMonotonic);
|
176
182
|
assert(ok);
|
177
183
|
buffer = MemoryKit::mbuf(buffer, 0, bufferSize);
|
178
184
|
SKC_TRACE(client, 3, "Header data: \"" << cEscapeString(
|
@@ -182,7 +188,7 @@ Controller::sendHeaderToAppWithSessionProtocol(Client *client, Request *req) {
|
|
182
188
|
char *buffer = (char *) psg_pnalloc(req->pool, bufferSize);
|
183
189
|
|
184
190
|
ok = constructHeaderForSessionProtocol(req, buffer,
|
185
|
-
bufferSize, state,
|
191
|
+
bufferSize, state, deltaMonotonic);
|
186
192
|
assert(ok);
|
187
193
|
SKC_TRACE(client, 3, "Header data: \"" << cEscapeString(
|
188
194
|
StaticString(buffer, bufferSize)) << "\"");
|
@@ -24,6 +24,7 @@
|
|
24
24
|
* THE SOFTWARE.
|
25
25
|
*/
|
26
26
|
#include <Core/Controller.h>
|
27
|
+
#include <Integrations/LibevJsonUtils.h>
|
27
28
|
|
28
29
|
/*************************************************************************
|
29
30
|
*
|
@@ -86,7 +87,7 @@ Controller::inspectStateAsJson() const {
|
|
86
87
|
Json::Value
|
87
88
|
Controller::inspectClientStateAsJson(const Client *client) const {
|
88
89
|
Json::Value doc = ParentClass::inspectClientStateAsJson(client);
|
89
|
-
doc["connected_at"] =
|
90
|
+
doc["connected_at"] = evTimeToJson(client->connectedAt, ev_now(getLoop()));
|
90
91
|
return doc;
|
91
92
|
}
|
92
93
|
|
@@ -97,7 +98,7 @@ Controller::inspectRequestStateAsJson(const Request *req) const {
|
|
97
98
|
const AppResponse *resp = &req->appResponse;
|
98
99
|
|
99
100
|
if (req->startedAt != 0) {
|
100
|
-
doc["started_at"] =
|
101
|
+
doc["started_at"] = evTimeToJson(req->startedAt, ev_now(getLoop()));
|
101
102
|
}
|
102
103
|
doc["state"] = req->getStateString();
|
103
104
|
if (req->stickySession) {
|
data/src/agent/Core/CoreMain.cpp
CHANGED
@@ -344,7 +344,7 @@ private:
|
|
344
344
|
try {
|
345
345
|
const size_t UNIX_PATH_MAX = sizeof(((struct sockaddr_un *) 0)->sun_path);
|
346
346
|
string data = "You have control 1.0\n"
|
347
|
-
"passenger_root: " + config->resourceLocator->
|
347
|
+
"passenger_root: " + config->resourceLocator->getInstallSpec() + "\n"
|
348
348
|
"ruby_libdir: " + config->resourceLocator->getRubyLibDir() + "\n"
|
349
349
|
"passenger_version: " PASSENGER_VERSION "\n"
|
350
350
|
"UNIX_PATH_MAX: " + toString(UNIX_PATH_MAX) + "\n";
|
@@ -270,7 +270,7 @@ private:
|
|
270
270
|
try {
|
271
271
|
const size_t UNIX_PATH_MAX = sizeof(((struct sockaddr_un *) 0)->sun_path);
|
272
272
|
string data = "You have control 1.0\n"
|
273
|
-
"passenger_root: " + config->resourceLocator->
|
273
|
+
"passenger_root: " + config->resourceLocator->getInstallSpec() + "\n"
|
274
274
|
"passenger_version: " PASSENGER_VERSION "\n"
|
275
275
|
"ruby_libdir: " + config->resourceLocator->getRubyLibDir() + "\n"
|
276
276
|
"gupid: " + details.gupid + "\n"
|
@@ -461,7 +461,7 @@ protected:
|
|
461
461
|
* <em>timeout</em> miliseconds for the process to exit.
|
462
462
|
*/
|
463
463
|
static int timedWaitpid(pid_t pid, int *status, unsigned long long timeout) {
|
464
|
-
Timer timer;
|
464
|
+
Timer<SystemTime::GRAN_10MSEC> timer;
|
465
465
|
int ret;
|
466
466
|
|
467
467
|
do {
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -32,7 +32,6 @@
|
|
32
32
|
|
33
33
|
#include <string>
|
34
34
|
|
35
|
-
#include <uv.h>
|
36
35
|
#include <StaticString.h>
|
37
36
|
#include <Exceptions.h>
|
38
37
|
#include <Utils/StrIntUtils.h>
|
@@ -82,7 +81,7 @@ public:
|
|
82
81
|
pos = appendData(pos, end, "BEGIN: ");
|
83
82
|
pos = appendData(pos, end, id);
|
84
83
|
pos = appendData(pos, end, " (");
|
85
|
-
pos = appendData(pos, end, usecToString(
|
84
|
+
pos = appendData(pos, end, usecToString(SystemTime::getMonotonicUsec()));
|
86
85
|
pos = appendData(pos, end, ",");
|
87
86
|
if (getrusage(RUSAGE_SELF, &usage) == -1) {
|
88
87
|
int e = errno;
|
@@ -122,7 +121,7 @@ public:
|
|
122
121
|
}
|
123
122
|
pos = appendData(pos, end, id);
|
124
123
|
pos = appendData(pos, end, " (");
|
125
|
-
pos = appendData(pos, end, usecToString(
|
124
|
+
pos = appendData(pos, end, usecToString(SystemTime::getMonotonicUsec()));
|
126
125
|
pos = appendData(pos, end, ",");
|
127
126
|
if (getrusage(RUSAGE_SELF, &usage) == -1) {
|
128
127
|
int e = errno;
|
data/src/agent/Shared/Base.cpp
CHANGED
@@ -64,6 +64,7 @@
|
|
64
64
|
#include <Logging.h>
|
65
65
|
#include <ResourceLocator.h>
|
66
66
|
#include <Utils.h>
|
67
|
+
#include <Utils/SystemTime.h>
|
67
68
|
#include <Utils/StrIntUtils.h>
|
68
69
|
#ifdef __linux__
|
69
70
|
#include <ResourceLocator.h>
|
@@ -1500,6 +1501,7 @@ initializeAgent(int argc, char **argv[], const char *processName,
|
|
1500
1501
|
if (hasEnvOption("PASSENGER_SIMULATE_SYSCALL_FAILURES")) {
|
1501
1502
|
initializeSyscallFailureSimulation(processName);
|
1502
1503
|
}
|
1504
|
+
SystemTime::initialize();
|
1503
1505
|
setvbuf(stdout, NULL, _IONBF, 0);
|
1504
1506
|
setvbuf(stderr, NULL, _IONBF, 0);
|
1505
1507
|
|
@@ -1645,4 +1647,34 @@ shutdownAgent(VariantMap *agentOptions) {
|
|
1645
1647
|
oxt::shutdown();
|
1646
1648
|
}
|
1647
1649
|
|
1650
|
+
void
|
1651
|
+
restoreOomScore(VariantMap *agentOptions) {
|
1652
|
+
TRACE_POINT();
|
1653
|
+
|
1654
|
+
string score = agentOptions->get("original_oom_score", false);
|
1655
|
+
if (score.empty()) {
|
1656
|
+
return;
|
1657
|
+
}
|
1658
|
+
|
1659
|
+
FILE *f;
|
1660
|
+
bool legacy = false;
|
1661
|
+
|
1662
|
+
if (score.at(0) == 'l') {
|
1663
|
+
legacy = true;
|
1664
|
+
score = score.substr(1);
|
1665
|
+
f = fopen("/proc/self/oom_adj", "w");
|
1666
|
+
} else {
|
1667
|
+
f = fopen("/proc/self/oom_score_adj", "w");
|
1668
|
+
}
|
1669
|
+
|
1670
|
+
if (f != NULL) {
|
1671
|
+
fprintf(f, "%s\n", score.c_str());
|
1672
|
+
fclose(f);
|
1673
|
+
} else {
|
1674
|
+
P_WARN("Unable to set OOM score to " << score << " (legacy: " << legacy
|
1675
|
+
<< ") due to error: " << strerror(errno)
|
1676
|
+
<< " (process will remain at inherited OOM score)");
|
1677
|
+
}
|
1678
|
+
}
|
1679
|
+
|
1648
1680
|
} // namespace Passenger
|
data/src/agent/Shared/Base.h
CHANGED
@@ -203,7 +203,7 @@ protected:
|
|
203
203
|
* <em>timeout</em> miliseconds for the process to exit.
|
204
204
|
*/
|
205
205
|
static int timedWaitPid(pid_t pid, int *status, unsigned long long timeout) {
|
206
|
-
Timer timer;
|
206
|
+
Timer<SystemTime::GRAN_10MSEC> timer;
|
207
207
|
int ret;
|
208
208
|
|
209
209
|
do {
|
@@ -308,8 +308,6 @@ public:
|
|
308
308
|
* only affects the watchdog but not agents. */
|
309
309
|
setpgid(getpid(), getpid());
|
310
310
|
|
311
|
-
setOomScore(oldOomScore);
|
312
|
-
|
313
311
|
try {
|
314
312
|
execProgram();
|
315
313
|
} catch (...) {
|
@@ -162,7 +162,7 @@ static void cleanup(const WorkingObjectsPtr &wo);
|
|
162
162
|
/***** Functions *****/
|
163
163
|
|
164
164
|
static FILE *
|
165
|
-
|
165
|
+
openOomAdjFileGetType(const char *mode, OomFileType &type) {
|
166
166
|
FILE *f = fopen("/proc/self/oom_score_adj", mode);
|
167
167
|
if (f == NULL) {
|
168
168
|
f = fopen("/proc/self/oom_adj", mode);
|
@@ -178,6 +178,16 @@ openOomAdjFile(const char *mode, OomFileType &type) {
|
|
178
178
|
}
|
179
179
|
}
|
180
180
|
|
181
|
+
static FILE *
|
182
|
+
openOomAdjFileForcedType(const char *mode, OomFileType &type) {
|
183
|
+
if (type == OOM_SCORE_ADJ) {
|
184
|
+
return fopen("/proc/self/oom_score_adj", mode);
|
185
|
+
} else {
|
186
|
+
assert(type == OOM_ADJ);
|
187
|
+
return fopen("/proc/self/oom_adj", mode);
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
181
191
|
/**
|
182
192
|
* Linux-only way to change OOM killer configuration for
|
183
193
|
* current process. Requires root privileges, which we
|
@@ -191,14 +201,24 @@ setOomScore(const StaticString &score) {
|
|
191
201
|
|
192
202
|
FILE *f;
|
193
203
|
OomFileType type;
|
204
|
+
string filteredScore;
|
194
205
|
|
195
|
-
|
206
|
+
if (score.at(0) == 'l') {
|
207
|
+
filteredScore = score.substr(1);
|
208
|
+
type = OOM_ADJ;
|
209
|
+
} else {
|
210
|
+
filteredScore = score;
|
211
|
+
type = OOM_SCORE_ADJ;
|
212
|
+
}
|
213
|
+
f = openOomAdjFileForcedType("w", type);
|
196
214
|
if (f != NULL) {
|
197
|
-
size_t ret = fwrite(
|
215
|
+
size_t ret = fwrite(filteredScore.data(), 1, filteredScore.size(), f);
|
198
216
|
// We can't do anything about failures, so ignore compiler
|
199
217
|
// warnings about not doing anything with the result.
|
200
218
|
(void) ret;
|
201
219
|
fclose(f);
|
220
|
+
} else {
|
221
|
+
P_WARN("setOomScore(" << filteredScore << ", " << type << ") failed due to error: " << strerror(errno));
|
202
222
|
}
|
203
223
|
}
|
204
224
|
|
@@ -211,10 +231,14 @@ setOomScoreNeverKill() {
|
|
211
231
|
FILE *f;
|
212
232
|
OomFileType type;
|
213
233
|
|
214
|
-
f =
|
234
|
+
f = openOomAdjFileGetType("r", type);
|
215
235
|
if (f == NULL) {
|
216
236
|
return "";
|
217
237
|
}
|
238
|
+
// mark if this is a legacy score so we won't try to write it as OOM_SCORE_ADJ
|
239
|
+
if (type == OOM_ADJ) {
|
240
|
+
oldScore.append("l");
|
241
|
+
}
|
218
242
|
char buf[1024];
|
219
243
|
size_t bytesRead;
|
220
244
|
while (true) {
|
@@ -230,7 +254,7 @@ setOomScoreNeverKill() {
|
|
230
254
|
}
|
231
255
|
fclose(f);
|
232
256
|
|
233
|
-
f =
|
257
|
+
f = openOomAdjFileForcedType("w", type);
|
234
258
|
if (f == NULL) {
|
235
259
|
return "";
|
236
260
|
}
|
@@ -397,7 +421,7 @@ cleanupAgentsInBackground(const WorkingObjectsPtr &wo, vector<AgentWatcherPtr> &
|
|
397
421
|
// Child
|
398
422
|
try {
|
399
423
|
vector<AgentWatcherPtr>::const_iterator it;
|
400
|
-
Timer timer(false);
|
424
|
+
Timer<SystemTime::GRAN_10MSEC> timer(false);
|
401
425
|
fd_set fds, fds2;
|
402
426
|
int max, agentProcessesDone;
|
403
427
|
unsigned long long deadline = 30000; // miliseconds
|
@@ -781,6 +805,7 @@ initializeBareEssentials(int argc, char *argv[], WorkingObjectsPtr &wo) {
|
|
781
805
|
agentsOptions = new VariantMap();
|
782
806
|
*agentsOptions = initializeAgent(argc, &argv, SHORT_PROGRAM_NAME " watchdog",
|
783
807
|
parseOptions, NULL, 2);
|
808
|
+
agentsOptions->set("original_oom_score", oldOomScore);
|
784
809
|
|
785
810
|
// Start all sub-agents with this environment variable.
|
786
811
|
setenv("PASSENGER_USE_FEEDBACK_FD", "true", 1);
|