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.

Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +17 -0
  3. data/CONTRIBUTORS +1 -0
  4. data/build/cxx_dependency_map.rb +113 -157
  5. data/build/cxx_tests.rb +8 -1
  6. data/src/agent/Core/ApplicationPool/TestSession.h +5 -1
  7. data/src/agent/Core/Controller/CheckoutSession.cpp +1 -1
  8. data/src/agent/Core/Controller/ForwardResponse.cpp +9 -0
  9. data/src/agent/Core/Controller/InternalUtils.cpp +9 -1
  10. data/src/agent/Core/Controller/SendRequest.cpp +13 -7
  11. data/src/agent/Core/Controller/StateInspectionAndConfiguration.cpp +3 -2
  12. data/src/agent/Core/CoreMain.cpp +3 -0
  13. data/src/agent/Core/SpawningKit/SmartSpawner.h +1 -1
  14. data/src/agent/Core/SpawningKit/Spawner.h +2 -2
  15. data/src/agent/Core/UnionStation/StopwatchLog.h +3 -4
  16. data/src/agent/Shared/Base.cpp +32 -0
  17. data/src/agent/Shared/Base.h +2 -0
  18. data/src/agent/UstRouter/UstRouterMain.cpp +3 -0
  19. data/src/agent/Watchdog/AgentWatcher.cpp +1 -3
  20. data/src/agent/Watchdog/WatchdogMain.cpp +31 -6
  21. data/src/apache2_module/Hooks.cpp +2 -2
  22. data/src/cxx_supportlib/BackgroundEventLoop.cpp +12 -2
  23. data/src/cxx_supportlib/Constants.h +1 -1
  24. data/src/cxx_supportlib/DataStructures/LString.cpp +39 -0
  25. data/src/cxx_supportlib/DataStructures/LString.h +35 -6
  26. data/src/cxx_supportlib/FileDescriptor.h +3 -1
  27. data/src/cxx_supportlib/Integrations/LibevJsonUtils.h +92 -0
  28. data/src/cxx_supportlib/ResourceLocator.h +10 -8
  29. data/src/cxx_supportlib/ServerKit/CookieUtils.h +4 -0
  30. data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +2 -0
  31. data/src/cxx_supportlib/ServerKit/HttpServer.h +6 -2
  32. data/src/cxx_supportlib/Utils.cpp +4 -5
  33. data/src/cxx_supportlib/Utils.h +2 -2
  34. data/src/cxx_supportlib/Utils/IOUtils.cpp +1 -1
  35. data/src/cxx_supportlib/Utils/JsonUtils.h +12 -10
  36. data/src/cxx_supportlib/Utils/MessagePassing.h +4 -4
  37. data/src/cxx_supportlib/Utils/StrIntUtils.cpp +7 -3
  38. data/src/cxx_supportlib/Utils/SystemTime.cpp +15 -4
  39. data/src/cxx_supportlib/Utils/SystemTime.h +228 -54
  40. data/src/cxx_supportlib/Utils/Timer.h +14 -41
  41. data/src/cxx_supportlib/WatchdogLauncher.h +1 -1
  42. data/src/cxx_supportlib/vendor-copy/libuv/Makefile.in +198 -59
  43. data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/output.0 +15477 -0
  44. data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/output.1 +15477 -0
  45. data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/requests +324 -0
  46. data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/traces.0 +3105 -0
  47. data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/traces.1 +703 -0
  48. data/src/cxx_supportlib/vendor-copy/libuv/configure +115 -12
  49. data/src/cxx_supportlib/vendor-copy/libuv/ltmain.sh +15 -8
  50. data/src/cxx_supportlib/vendor-copy/libuv/m4/ltversion.m4 +5 -5
  51. data/src/cxx_supportlib/vendor-modified/psg_sysqueue.h +1 -0
  52. data/src/nginx_module/ngx_http_passenger_module.c +1 -1
  53. data/src/nodejs_supportlib/phusion_passenger/ustreporter.js +1 -1
  54. data/src/ruby_native_extension/passenger_native_support.c +1 -1
  55. data/src/ruby_supportlib/phusion_passenger.rb +15 -1
  56. data/src/ruby_supportlib/phusion_passenger/common_library.rb +4 -0
  57. data/src/ruby_supportlib/phusion_passenger/packaging.rb +1 -0
  58. data/src/ruby_supportlib/phusion_passenger/ruby_core_io_enhancements.rb +5 -20
  59. metadata +9 -2
@@ -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
- command = "valgrind --dsymutil=yes --db-attach=yes --child-silent-after-fork=yes #{command}"
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 = (unsigned long long) (ev_now(getLoop()) * 1000000);
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
- SKC_WARN(*client, "Sending 502 response: application did not send a complete response");
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 delta_monotonic = boost::to_string(SystemTime::getUsec() - (uv_hrtime() / 1000));
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, delta_monotonic);
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, delta_monotonic);
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, delta_monotonic);
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"] = timeToJson(client->connectedAt * 1000000.0);
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"] = timeToJson(req->startedAt * 1000000.0);
101
+ doc["started_at"] = evTimeToJson(req->startedAt, ev_now(getLoop()));
101
102
  }
102
103
  doc["state"] = req->getStateString();
103
104
  if (req->stickySession) {
@@ -1235,6 +1235,9 @@ coreMain(int argc, char *argv[]) {
1235
1235
  preinitialize, 2);
1236
1236
  setAgentsOptionsDefaults();
1237
1237
  sanityCheckOptions();
1238
+
1239
+ restoreOomScore(agentsOptions);
1240
+
1238
1241
  ret = runCore();
1239
1242
  shutdownAgent(agentsOptions);
1240
1243
  return ret;
@@ -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->getRoot() + "\n"
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->getRoot() + "\n"
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-2015 Phusion Holding B.V.
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(uv_hrtime() / 1000));
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(uv_hrtime() / 1000));
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;
@@ -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
@@ -51,6 +51,8 @@ void installDiagnosticsDumper(DiagnosticsDumper func, void *userData);
51
51
 
52
52
  void shutdownAgent(VariantMap *agentOptions);
53
53
 
54
+ void restoreOomScore(VariantMap *agentOptions);
55
+
54
56
  }
55
57
 
56
58
  #endif /* _PASSENGER_AGENT_BASE_H_ */
@@ -666,5 +666,8 @@ ustRouterMain(int argc, char *argv[]) {
666
666
 
667
667
  setAgentsOptionsDefaults();
668
668
  sanityCheckOptions();
669
+
670
+ restoreOomScore(agentsOptions);
671
+
669
672
  return runUstRouter();
670
673
  }
@@ -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
- openOomAdjFile(const char *mode, OomFileType &type) {
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
- f = openOomAdjFile("w", type);
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(score.data(), 1, score.size(), f);
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 = openOomAdjFile("r", type);
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 = openOomAdjFile("w", type);
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);