passenger 5.0.8 → 5.0.9

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 (168) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +20 -0
  5. data/CHANGELOG +21 -0
  6. data/bin/passenger-install-apache2-module +3 -1
  7. data/build/agents.rb +7 -5
  8. data/build/basics.rb +3 -3
  9. data/build/common_library.rb +52 -30
  10. data/build/cxx_tests.rb +20 -13
  11. data/build/misc.rb +5 -5
  12. data/doc/Design and Architecture.html +1 -1
  13. data/doc/Design and Architecture.txt +1 -1
  14. data/doc/Packaging.html +4 -4
  15. data/doc/Packaging.txt.md +4 -4
  16. data/doc/Users guide Apache.html +22 -9
  17. data/doc/Users guide Apache.idmap.txt +4 -2
  18. data/doc/Users guide Apache.txt +2 -0
  19. data/doc/Users guide Nginx.html +22 -9
  20. data/doc/Users guide Nginx.idmap.txt +4 -2
  21. data/doc/Users guide Nginx.txt +2 -0
  22. data/doc/Users guide Standalone.html +14 -9
  23. data/doc/Users guide Standalone.idmap.txt +4 -2
  24. data/doc/users_guide_snippets/installation.txt +10 -6
  25. data/ext/apache2/Hooks.cpp +13 -2
  26. data/ext/common/ApplicationPool2/Pool/Inspection.h +8 -3
  27. data/ext/common/BackgroundEventLoop.cpp +249 -67
  28. data/ext/common/BackgroundEventLoop.h +5 -5
  29. data/ext/common/Constants.h +1 -1
  30. data/ext/common/InstanceDirectory.h +8 -6
  31. data/ext/common/ServerKit/Context.h +8 -2
  32. data/ext/common/ServerKit/FileBufferedChannel.h +262 -226
  33. data/ext/common/ServerKit/HeaderTable.h +28 -3
  34. data/ext/common/ServerKit/HttpHeaderParser.h +37 -13
  35. data/ext/common/ServerKit/HttpServer.h +17 -1
  36. data/ext/common/ServerKit/Implementation.cpp +2 -0
  37. data/ext/common/ServerKit/Server.h +25 -28
  38. data/ext/common/Utils/IOUtils.cpp +11 -0
  39. data/ext/common/Utils/ProcessMetricsCollector.h +4 -0
  40. data/ext/common/Utils/StrIntUtils.cpp +11 -7
  41. data/ext/common/Utils/StrIntUtils.h +1 -1
  42. data/ext/common/Utils/StrIntUtilsNoStrictAliasing.cpp +21 -16
  43. data/ext/common/agents/Base.cpp +6 -0
  44. data/ext/common/agents/Base.h +2 -0
  45. data/ext/common/agents/HelperAgent/AdminServer.h +25 -25
  46. data/ext/common/agents/HelperAgent/Main.cpp +37 -12
  47. data/ext/common/agents/HelperAgent/RequestHandler.h +18 -20
  48. data/ext/common/agents/HelperAgent/RequestHandler/AppResponse.h +4 -0
  49. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +10 -6
  50. data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +2 -0
  51. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +1 -1
  52. data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +1 -1
  53. data/ext/common/agents/HelperAgent/RequestHandler/Utils.cpp +9 -2
  54. data/ext/common/agents/HelperAgent/ResponseCache.h +11 -11
  55. data/ext/common/agents/LoggingAgent/AdminServer.h +8 -8
  56. data/ext/common/agents/LoggingAgent/Main.cpp +6 -5
  57. data/ext/common/agents/Watchdog/AdminServer.h +13 -13
  58. data/ext/common/agents/Watchdog/Main.cpp +8 -3
  59. data/ext/libuv/.gitignore +72 -0
  60. data/ext/libuv/AUTHORS +199 -0
  61. data/ext/libuv/ChangeLog +2023 -0
  62. data/ext/libuv/LICENSE +46 -0
  63. data/ext/libuv/Makefile.am +336 -0
  64. data/ext/libuv/README.md +197 -0
  65. data/ext/libuv/checksparse.sh +233 -0
  66. data/ext/libuv/common.gypi +210 -0
  67. data/ext/libuv/configure.ac +67 -0
  68. data/ext/libuv/gyp_uv.py +96 -0
  69. data/ext/libuv/include/android-ifaddrs.h +54 -0
  70. data/ext/libuv/include/pthread-fixes.h +72 -0
  71. data/ext/libuv/include/tree.h +768 -0
  72. data/ext/libuv/include/uv-aix.h +32 -0
  73. data/ext/libuv/include/uv-bsd.h +34 -0
  74. data/ext/libuv/include/uv-darwin.h +61 -0
  75. data/ext/libuv/include/uv-errno.h +418 -0
  76. data/ext/libuv/include/uv-linux.h +34 -0
  77. data/ext/libuv/include/uv-sunos.h +44 -0
  78. data/ext/libuv/include/uv-threadpool.h +37 -0
  79. data/ext/libuv/include/uv-unix.h +383 -0
  80. data/ext/libuv/include/uv-version.h +39 -0
  81. data/ext/libuv/include/uv.h +1455 -0
  82. data/ext/libuv/libuv.pc.in +11 -0
  83. data/ext/libuv/m4/.gitignore +4 -0
  84. data/ext/libuv/m4/as_case.m4 +21 -0
  85. data/ext/libuv/m4/libuv-check-flags.m4 +319 -0
  86. data/ext/libuv/src/fs-poll.c +255 -0
  87. data/ext/libuv/src/heap-inl.h +245 -0
  88. data/ext/libuv/src/inet.c +313 -0
  89. data/ext/libuv/src/queue.h +92 -0
  90. data/ext/libuv/src/threadpool.c +303 -0
  91. data/ext/libuv/src/unix/aix.c +1240 -0
  92. data/ext/libuv/src/unix/android-ifaddrs.c +703 -0
  93. data/ext/libuv/src/unix/async.c +284 -0
  94. data/ext/libuv/src/unix/atomic-ops.h +60 -0
  95. data/ext/libuv/src/unix/core.c +985 -0
  96. data/ext/libuv/src/unix/darwin-proctitle.c +206 -0
  97. data/ext/libuv/src/unix/darwin.c +331 -0
  98. data/ext/libuv/src/unix/dl.c +83 -0
  99. data/ext/libuv/src/unix/freebsd.c +435 -0
  100. data/ext/libuv/src/unix/fs.c +1189 -0
  101. data/ext/libuv/src/unix/fsevents.c +899 -0
  102. data/ext/libuv/src/unix/getaddrinfo.c +202 -0
  103. data/ext/libuv/src/unix/getnameinfo.c +120 -0
  104. data/ext/libuv/src/unix/internal.h +314 -0
  105. data/ext/libuv/src/unix/kqueue.c +418 -0
  106. data/ext/libuv/src/unix/linux-core.c +876 -0
  107. data/ext/libuv/src/unix/linux-inotify.c +257 -0
  108. data/ext/libuv/src/unix/linux-syscalls.c +471 -0
  109. data/ext/libuv/src/unix/linux-syscalls.h +158 -0
  110. data/ext/libuv/src/unix/loop-watcher.c +63 -0
  111. data/ext/libuv/src/unix/loop.c +135 -0
  112. data/ext/libuv/src/unix/netbsd.c +368 -0
  113. data/ext/libuv/src/unix/openbsd.c +384 -0
  114. data/ext/libuv/src/unix/pipe.c +288 -0
  115. data/ext/libuv/src/unix/poll.c +113 -0
  116. data/ext/libuv/src/unix/process.c +551 -0
  117. data/ext/libuv/src/unix/proctitle.c +102 -0
  118. data/ext/libuv/src/unix/pthread-fixes.c +103 -0
  119. data/ext/libuv/src/unix/signal.c +465 -0
  120. data/ext/libuv/src/unix/spinlock.h +53 -0
  121. data/ext/libuv/src/unix/stream.c +1598 -0
  122. data/ext/libuv/src/unix/sunos.c +763 -0
  123. data/ext/libuv/src/unix/tcp.c +327 -0
  124. data/ext/libuv/src/unix/thread.c +519 -0
  125. data/ext/libuv/src/unix/timer.c +172 -0
  126. data/ext/libuv/src/unix/tty.c +265 -0
  127. data/ext/libuv/src/unix/udp.c +833 -0
  128. data/ext/libuv/src/uv-common.c +544 -0
  129. data/ext/libuv/src/uv-common.h +214 -0
  130. data/ext/libuv/src/version.c +49 -0
  131. data/ext/libuv/uv.gyp +487 -0
  132. data/ext/nginx/ContentHandler.c +21 -10
  133. data/ext/nginx/ngx_http_passenger_module.c +7 -0
  134. data/ext/oxt/implementation.cpp +9 -2
  135. data/ext/oxt/initialize.hpp +5 -1
  136. data/lib/phusion_passenger.rb +3 -3
  137. data/lib/phusion_passenger/admin_tools/instance.rb +10 -6
  138. data/lib/phusion_passenger/admin_tools/instance_registry.rb +6 -2
  139. data/lib/phusion_passenger/packaging.rb +3 -4
  140. data/lib/phusion_passenger/platform_info.rb +13 -1
  141. data/lib/phusion_passenger/platform_info/apache.rb +15 -4
  142. data/lib/phusion_passenger/platform_info/apache_detector.rb +5 -1
  143. data/lib/phusion_passenger/rack/thread_handler_extension.rb +184 -99
  144. data/lib/phusion_passenger/request_handler/thread_handler.rb +13 -6
  145. data/lib/phusion_passenger/standalone/start_command.rb +2 -2
  146. data/resources/templates/apache2/apache_install_broken.txt.erb +2 -1
  147. metadata +99 -22
  148. metadata.gz.asc +7 -7
  149. data/ext/libeio/Changes +0 -76
  150. data/ext/libeio/LICENSE +0 -36
  151. data/ext/libeio/Makefile.am +0 -15
  152. data/ext/libeio/Makefile.in +0 -694
  153. data/ext/libeio/aclocal.m4 +0 -9418
  154. data/ext/libeio/autogen.sh +0 -3
  155. data/ext/libeio/config.guess +0 -1540
  156. data/ext/libeio/config.h.in +0 -136
  157. data/ext/libeio/config.sub +0 -1779
  158. data/ext/libeio/configure +0 -14822
  159. data/ext/libeio/configure.ac +0 -22
  160. data/ext/libeio/demo.c +0 -194
  161. data/ext/libeio/ecb.h +0 -714
  162. data/ext/libeio/eio.c +0 -2818
  163. data/ext/libeio/eio.h +0 -414
  164. data/ext/libeio/install-sh +0 -520
  165. data/ext/libeio/libeio.m4 +0 -195
  166. data/ext/libeio/ltmain.sh +0 -9636
  167. data/ext/libeio/missing +0 -376
  168. data/ext/libeio/xthread.h +0 -166
@@ -43,7 +43,10 @@ extern const HashedStaticString HTTP_COOKIE;
43
43
  extern const HashedStaticString HTTP_SET_COOKIE;
44
44
 
45
45
  struct Header {
46
+ /** Downcased version of the key, for case-insensitive lookup. */
46
47
  LString key;
48
+ /** Original, unmodified key. */
49
+ LString origKey;
47
50
  LString val;
48
51
  boost::uint32_t hash;
49
52
  };
@@ -225,6 +228,16 @@ public:
225
228
  return const_cast<Cell *>(static_cast<const HeaderTable *>(this)->lookupCell(key));
226
229
  }
227
230
 
231
+ OXT_FORCE_INLINE
232
+ Header *lookupHeader(const HashedStaticString &key) {
233
+ Cell *cell = lookupCell(key);
234
+ if (cell != NULL) {
235
+ return cell->header;
236
+ } else {
237
+ return NULL;
238
+ }
239
+ }
240
+
228
241
  const LString *lookup(const HashedStaticString &key) const {
229
242
  const Cell * const cell = lookupCell(key);
230
243
  if (cell != NULL) {
@@ -285,6 +298,7 @@ public:
285
298
  part = next;
286
299
  }
287
300
  psg_lstr_deinit(&header->key);
301
+ psg_lstr_deinit(&header->origKey);
288
302
  *headerPtr = NULL;
289
303
  return;
290
304
  } else {
@@ -294,15 +308,24 @@ public:
294
308
  }
295
309
  }
296
310
 
297
- Header *insert(psg_pool_t *pool, const HashedStaticString &name,
311
+ Header *insert(psg_pool_t *pool, const StaticString &name,
298
312
  const StaticString &value)
299
313
  {
300
314
  Header *header = (Header *) psg_palloc(pool, sizeof(Header));
315
+
316
+ char *downcasedName = (char *) psg_pnalloc(pool, name.size());
317
+ convertLowerCase((const unsigned char *) name.data(),
318
+ (unsigned char *) downcasedName, name.size());
301
319
  psg_lstr_init(&header->key);
302
- psg_lstr_append(&header->key, pool, name.data(), name.size());
320
+ psg_lstr_append(&header->key, pool, downcasedName, name.size());
321
+
322
+ psg_lstr_init(&header->origKey);
323
+ psg_lstr_append(&header->origKey, pool, name.data(), name.size());
324
+
303
325
  psg_lstr_init(&header->val);
304
326
  psg_lstr_append(&header->val, pool, value.data(), value.size());
305
- header->hash = name.hash();
327
+
328
+ header->hash = HashedStaticString(downcasedName, name.size()).hash();
306
329
  insert(&header, pool);
307
330
  return header;
308
331
  }
@@ -320,6 +343,7 @@ public:
320
343
  // A previous iteration in this loop
321
344
  // could have made cell->header NULL.
322
345
  psg_lstr_deinit(&cell->header->key);
346
+ psg_lstr_deinit(&cell->header->origKey);
323
347
  psg_lstr_deinit(&cell->header->val);
324
348
  cell->header = NULL;
325
349
  }
@@ -335,6 +359,7 @@ public:
335
359
  // A previous iteration in this loop
336
360
  // could have made cell->header NULL.
337
361
  psg_lstr_deinit(&cell->header->key);
362
+ psg_lstr_deinit(&cell->header->origKey);
338
363
  psg_lstr_deinit(&cell->header->val);
339
364
  }
340
365
  *cell = *neighbor;
@@ -45,6 +45,7 @@ namespace ServerKit {
45
45
 
46
46
 
47
47
  extern const HashedStaticString HTTP_CONTENT_LENGTH;
48
+ extern const HashedStaticString HTTP_TRANSFER_ENCODING;
48
49
  extern const HashedStaticString HTTP_X_SENDFILE;
49
50
  extern const HashedStaticString HTTP_X_ACCEL_REDIRECT;
50
51
 
@@ -172,7 +173,7 @@ private:
172
173
  || self->state->state == HttpHeaderParserState::PARSING_HEADER_VALUE
173
174
  || self->state->state == HttpHeaderParserState::PARSING_FIRST_HEADER_VALUE)
174
175
  {
175
- // New header key encountered.
176
+ // New header field encountered.
176
177
 
177
178
  if (self->state->state == HttpHeaderParserState::PARSING_FIRST_HEADER_VALUE
178
179
  || self->state->state == HttpHeaderParserState::PARSING_HEADER_VALUE)
@@ -184,8 +185,10 @@ private:
184
185
  self->insertCurrentHeader();
185
186
  }
186
187
 
188
+ // Initialize new header field.
187
189
  self->state->currentHeader = (Header *) psg_palloc(self->pool, sizeof(Header));
188
190
  psg_lstr_init(&self->state->currentHeader->key);
191
+ psg_lstr_init(&self->state->currentHeader->origKey);
189
192
  psg_lstr_init(&self->state->currentHeader->val);
190
193
  self->state->hasher.reset();
191
194
  if (self->state->state == HttpHeaderParserState::PARSING_URL) {
@@ -195,12 +198,20 @@ private:
195
198
  }
196
199
  }
197
200
 
198
- psg_lstr_append(&self->state->currentHeader->key, self->pool,
201
+ psg_lstr_append(&self->state->currentHeader->origKey, self->pool,
199
202
  *self->currentBuffer, data, len);
200
- if (psg_lstr_first_byte(&self->state->currentHeader->key) != '!') {
201
- convertLowerCase((unsigned char *) const_cast<char *>(data), len);
203
+ if (psg_lstr_first_byte(&self->state->currentHeader->origKey) == '!') {
204
+ psg_lstr_append(&self->state->currentHeader->key, self->pool,
205
+ *self->currentBuffer, data, len);
206
+ self->state->hasher.update(data, len);
207
+ } else {
208
+ char *downcasedData = (char *) psg_pnalloc(self->pool, len);
209
+ convertLowerCase((const unsigned char *) data,
210
+ (unsigned char *) downcasedData, len);
211
+ psg_lstr_append(&self->state->currentHeader->key, self->pool,
212
+ downcasedData, len);
213
+ self->state->hasher.update(downcasedData, len);
202
214
  }
203
- self->state->hasher.update(data, len);
204
215
 
205
216
  return 0;
206
217
  }
@@ -359,6 +370,27 @@ private:
359
370
  message->httpState = Message::UPGRADED;
360
371
  message->bodyType = Message::RBT_UPGRADE;
361
372
  message->wantKeepAlive = false;
373
+ } else if (message->headers.lookup(HTTP_X_SENDFILE) != NULL
374
+ || message->headers.lookup(HTTP_X_ACCEL_REDIRECT) != NULL)
375
+ {
376
+ // If X-Sendfile or X-Accel-Redirect is set, pretend like the body
377
+ // is empty and disallow keep-alive. See:
378
+ // https://github.com/phusion/passenger/issues/1376
379
+ // https://github.com/phusion/passenger/issues/1498
380
+ //
381
+ // We don't set a fake "Content-Length: 0" header here
382
+ // because it's undefined what Content-Length means if
383
+ // X-Sendfile or X-Accel-Redirect are set.
384
+ //
385
+ // Because the response header no longer has any header
386
+ // that signals its size, keep-alive should also be disabled
387
+ // for the *request*. We already do that in RequestHandler's
388
+ // ForwardResponse.cpp.
389
+ message->httpState = Message::COMPLETE;
390
+ message->bodyType = Message::RBT_NO_BODY;
391
+ message->headers.erase(HTTP_CONTENT_LENGTH);
392
+ message->headers.erase(HTTP_TRANSFER_ENCODING);
393
+ message->wantKeepAlive = false;
362
394
  } else if (requestMethod == HTTP_HEAD
363
395
  || status / 100 == 1 // status 1xx
364
396
  || status == 204
@@ -370,14 +402,6 @@ private:
370
402
  message->httpState = Message::ONEHUNDRED_CONTINUE;
371
403
  }
372
404
  message->bodyType = Message::RBT_NO_BODY;
373
- } else if (message->headers.lookup(HTTP_X_SENDFILE) != NULL
374
- || message->headers.lookup(HTTP_X_ACCEL_REDIRECT) != NULL)
375
- {
376
- // Ignore Content-Length when X-Sendfile or X-Accel-Redirect is set.
377
- // See https://github.com/phusion/passenger/issues/1376
378
- message->httpState = Message::COMPLETE;
379
- message->bodyType = Message::RBT_NO_BODY;
380
- message->headers.erase(HTTP_CONTENT_LENGTH);
381
405
  } else if (state->parser.flags & F_CHUNKED) {
382
406
  if (contentLength == std::numeric_limits<boost::uint64_t>::max()) {
383
407
  message->httpState = Message::PARSING_CHUNKED_BODY;
@@ -980,10 +980,20 @@ protected:
980
980
  return false;
981
981
  }
982
982
 
983
+ virtual PassengerLogLevel getClientOutputErrorDisconnectionLogLevel(
984
+ Client *client, int errcode) const
985
+ {
986
+ if (errcode == EPIPE || errcode == ECONNRESET) {
987
+ return LVL_INFO;
988
+ } else {
989
+ return LVL_WARN;
990
+ }
991
+ }
992
+
983
993
  virtual void reinitializeClient(Client *client, int fd) {
984
994
  ParentClass::reinitializeClient(client, fd);
985
995
  client->requestsBegun = 0;
986
- client->currentRequest = NULL;
996
+ assert(client->currentRequest == NULL);
987
997
  }
988
998
 
989
999
  virtual void reinitializeRequest(Client *client, Request *req) {
@@ -1025,6 +1035,7 @@ protected:
1025
1035
  HeaderTable::Iterator it(req->headers);
1026
1036
  while (*it != NULL) {
1027
1037
  psg_lstr_deinit(&it->header->key);
1038
+ psg_lstr_deinit(&it->header->origKey);
1028
1039
  psg_lstr_deinit(&it->header->val);
1029
1040
  it.next();
1030
1041
  }
@@ -1032,6 +1043,7 @@ protected:
1032
1043
  it = HeaderTable::Iterator(req->secureHeaders);
1033
1044
  while (*it != NULL) {
1034
1045
  psg_lstr_deinit(&it->header->key);
1046
+ psg_lstr_deinit(&it->header->origKey);
1035
1047
  psg_lstr_deinit(&it->header->val);
1036
1048
  it.next();
1037
1049
  }
@@ -1073,6 +1085,10 @@ public:
1073
1085
 
1074
1086
  while (!STAILQ_EMPTY(&freeRequests)) {
1075
1087
  Request *request = STAILQ_FIRST(&freeRequests);
1088
+ if (request->pool != NULL) {
1089
+ psg_destroy_pool(request->pool);
1090
+ request->pool = NULL;
1091
+ }
1076
1092
  P_ASSERT_EQ(request->httpState, Request::IN_FREELIST);
1077
1093
  freeRequestCount--;
1078
1094
  STAILQ_REMOVE_HEAD(&freeRequests, nextRequest.freeRequest);
@@ -32,6 +32,7 @@ namespace ServerKit {
32
32
  extern const HashedStaticString HTTP_COOKIE;
33
33
  extern const HashedStaticString HTTP_SET_COOKIE;
34
34
  extern const HashedStaticString HTTP_CONTENT_LENGTH;
35
+ extern const HashedStaticString HTTP_TRANSFER_ENCODING;
35
36
  extern const HashedStaticString HTTP_X_SENDFILE;
36
37
  extern const HashedStaticString HTTP_X_ACCEL_REDIRECT;
37
38
  extern const char DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE[];
@@ -49,6 +50,7 @@ const unsigned int DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE_SIZE =
49
50
  const HashedStaticString HTTP_COOKIE("cookie");
50
51
  const HashedStaticString HTTP_SET_COOKIE("set-cookie");
51
52
  const HashedStaticString HTTP_CONTENT_LENGTH("content-length");
53
+ const HashedStaticString HTTP_TRANSFER_ENCODING("transfer-encoding");
52
54
  const HashedStaticString HTTP_X_SENDFILE("x-sendfile");
53
55
  const HashedStaticString HTTP_X_ACCEL_REDIRECT("x-accel-redirect");
54
56
 
@@ -79,6 +79,7 @@ using namespace oxt;
79
79
 
80
80
  #define SKS_NOTICE_FROM_STATIC(server, expr) P_NOTICE("[" << server->getServerName() << "] " << expr)
81
81
 
82
+ #define SKC_LOG(client, level, expr) SKC_LOG_FROM_STATIC(this, client, level, expr)
82
83
  #define SKC_ERROR(client, expr) SKC_ERROR_FROM_STATIC(this, client, expr)
83
84
  #define SKC_WARN(client, expr) SKC_WARN_FROM_STATIC(this, client, expr)
84
85
  #define SKC_NOTICE(client, expr) SKC_NOTICE_FROM_STATIC(this, client, expr)
@@ -90,40 +91,25 @@ using namespace oxt;
90
91
  #define SKC_TRACE_WITH_POS(client, level, file, line, expr) \
91
92
  SKC_TRACE_FROM_STATIC_WITH_POS(this, client, level, file, line, expr)
92
93
 
93
- #define SKC_ERROR_FROM_STATIC(server, client, expr) \
94
+ #define SKC_LOG_FROM_STATIC(server, client, level, expr) \
94
95
  do { \
95
- if (Passenger::getLogLevel() >= LVL_ERROR) { \
96
+ if (Passenger::getLogLevel() >= level) { \
96
97
  char _clientName[16]; \
97
98
  int _clientNameSize = server->getClientName((client), _clientName, sizeof(_clientName)); \
98
- P_ERROR("[Client " << StaticString(_clientName, _clientNameSize) << "] " << expr); \
99
+ P_LOG(level, __FILE__, __LINE__, \
100
+ "[Client " << StaticString(_clientName, _clientNameSize) << "] " << expr); \
99
101
  } \
100
102
  } while (0)
103
+ #define SKC_ERROR_FROM_STATIC(server, client, expr) \
104
+ SKC_LOG_FROM_STATIC(server, client, LVL_ERROR, expr)
101
105
  #define SKC_WARN_FROM_STATIC(server, client, expr) \
102
- do { \
103
- if (Passenger::getLogLevel() >= LVL_WARN) { \
104
- char _clientName[16]; \
105
- int _clientNameSize = server->getClientName((client), _clientName, sizeof(_clientName)); \
106
- P_WARN("[Client " << StaticString(_clientName, _clientNameSize) << "] " << expr); \
107
- } \
108
- } while (0)
106
+ SKC_LOG_FROM_STATIC(server, client, LVL_WARN, expr)
109
107
  #define SKC_NOTICE_FROM_STATIC(server, client, expr) \
110
- do { \
111
- if (Passenger::getLogLevel() >= LVL_WARN) { \
112
- char _clientName[16]; \
113
- int _clientNameSize = server->getClientName((client), _clientName, sizeof(_clientName)); \
114
- P_NOTICE("[Client " << StaticString(_clientName, _clientNameSize) << "] " << expr); \
115
- } \
116
- } while (0)
108
+ SKC_LOG_FROM_STATIC(server, client, LVL_NOTICE, expr)
117
109
  #define SKC_INFO_FROM_STATIC(server, client, expr) \
118
- do { \
119
- if (Passenger::getLogLevel() >= LVL_WARN) { \
120
- char _clientName[16]; \
121
- int _clientNameSize = server->getClientName((client), _clientName, sizeof(_clientName)); \
122
- P_INFO("[Client " << StaticString(_clientName, _clientNameSize) << "] " << expr); \
123
- } \
124
- } while (0)
110
+ SKC_LOG_FROM_STATIC(server, client, LVL_INFO, expr)
125
111
  #define SKC_DEBUG_FROM_STATIC(server, client, expr) \
126
- SKC_DEBUG_FROM_STATIC_WITH_POS(server, client, __FILE__, __LINE__, expr)
112
+ SKC_LOG_FROM_STATIC(server, client, LVL_DEBUG, expr)
127
113
  #define SKC_DEBUG_FROM_STATIC_WITH_POS(server, client, file, line, expr) \
128
114
  do { \
129
115
  if (OXT_UNLIKELY(Passenger::getLogLevel() >= LVL_DEBUG)) { \
@@ -452,6 +438,8 @@ private:
452
438
 
453
439
  void finishShutdown() {
454
440
  TRACE_POINT();
441
+ compact(LVL_INFO);
442
+
455
443
  SKS_NOTICE("Shutdown finished");
456
444
  serverState = FINISHED_SHUTDOWN;
457
445
  if (shutdownFinishCallback != NULL) {
@@ -629,7 +617,14 @@ protected:
629
617
  int ret = snprintf(message, sizeof(message),
630
618
  "client socket write error: %s (errno=%d)",
631
619
  getErrorDesc(errcode), errcode);
632
- disconnectWithError(&client, StaticString(message, ret));
620
+ disconnectWithError(&client, StaticString(message, ret),
621
+ getClientOutputErrorDisconnectionLogLevel(client, errcode));
622
+ }
623
+
624
+ virtual PassengerLogLevel getClientOutputErrorDisconnectionLogLevel(
625
+ Client *client, int errcode) const
626
+ {
627
+ return LVL_WARN;
633
628
  }
634
629
 
635
630
  virtual void reinitializeClient(Client *client, int fd) {
@@ -927,8 +922,10 @@ public:
927
922
  disconnect(client);
928
923
  }
929
924
 
930
- void disconnectWithError(Client **client, const StaticString &message) {
931
- SKC_WARN(*client, "Disconnecting client with error: " << message);
925
+ void disconnectWithError(Client **client, const StaticString &message,
926
+ PassengerLogLevel logLevel = LVL_WARN)
927
+ {
928
+ SKC_LOG(*client, logLevel, "Disconnecting client with error: " << message);
932
929
  disconnect(client);
933
930
  }
934
931
 
@@ -360,6 +360,17 @@ createTcpServer(const char *address, unsigned short port, unsigned int backlogSi
360
360
  }
361
361
  // Ignore SO_REUSEADDR error, it's not fatal.
362
362
 
363
+ #ifdef SO_REUSEPORT
364
+ optval = 1;
365
+ if (syscalls::setsockopt(fd, SOL_SOCKET, SO_REUSEPORT,
366
+ &optval, sizeof(optval)) == -1)
367
+ {
368
+ int e = errno;
369
+ fprintf(stderr, "so_reuseport failed: %s\n", strerror(e));
370
+ }
371
+ // Ignore SO_REUSEPORT error, it's not fatal.
372
+ #endif
373
+
363
374
  if (backlogSize == 0) {
364
375
  backlogSize = 1024;
365
376
  }
@@ -99,11 +99,15 @@ struct ProcessMetrics {
99
99
 
100
100
  ProcessMetrics() {
101
101
  pid = (pid_t) -1;
102
+ ppid = (pid_t) -1;
103
+ cpu = -1;
102
104
  rss = -1;
103
105
  pss = -1;
104
106
  privateDirty = -1;
105
107
  swap = -1;
106
108
  vmsize = -1;
109
+ processGroupId = (pid_t) -1;
110
+ uid = (uid_t) -1;
107
111
  }
108
112
 
109
113
  bool isValid() const {
@@ -458,7 +458,10 @@ atol(const string &s) {
458
458
  #if !defined(__x86_64__) && !defined(__x86__)
459
459
  // x86 and x86_64 optimized version is implemented in StrIntUtilsNoStrictAliasing.cpp.
460
460
  void
461
- convertLowerCase(unsigned char *data, size_t len) {
461
+ convertLowerCase(const unsigned char * restrict data,
462
+ unsigned char * restrict output,
463
+ size_t len)
464
+ {
462
465
  static const boost::uint8_t gsToLowerMap[256] = {
463
466
  '\0', 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, '\t',
464
467
  '\n', 0x0b, 0x0c, '\r', 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
@@ -492,16 +495,17 @@ atol(const string &s) {
492
495
  const size_t imax = len / 4;
493
496
  size_t i;
494
497
 
495
- for (i = 0; i < imax; i++, data += 4) {
496
- data[0] = (unsigned char) gsToLowerMap[data[0]];
497
- data[1] = (unsigned char) gsToLowerMap[data[1]];
498
- data[2] = (unsigned char) gsToLowerMap[data[2]];
499
- data[3] = (unsigned char) gsToLowerMap[data[3]];
498
+ for (i = 0; i < imax; i++, data += 4, output += 4) {
499
+ output[0] = (unsigned char) gsToLowerMap[data[0]];
500
+ output[1] = (unsigned char) gsToLowerMap[data[1]];
501
+ output[2] = (unsigned char) gsToLowerMap[data[2]];
502
+ output[3] = (unsigned char) gsToLowerMap[data[3]];
500
503
  }
501
504
 
502
505
  while (data < end) {
503
- *data = (unsigned char) gsToLowerMap[*data];
506
+ *output = (unsigned char) gsToLowerMap[*data];
504
507
  data++;
508
+ output++;
505
509
  }
506
510
  }
507
511
  #endif
@@ -388,7 +388,7 @@ roundUp(IntegerType number, IntegerType multiple) {
388
388
  /**
389
389
  * Converts the given character array to lowercase.
390
390
  */
391
- void convertLowerCase(unsigned char *data, size_t len);
391
+ void convertLowerCase(const unsigned char * restrict data, unsigned char * restrict output, size_t len);
392
392
 
393
393
  /**
394
394
  * Compare two strings using a constant time algorithm to avoid timing attacks.
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2014 Phusion
3
+ * Copyright (c) 2014-2015 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -25,6 +25,7 @@
25
25
 
26
26
  #include <boost/cstdint.hpp>
27
27
  #include <cstddef>
28
+ #include <Utils/StrIntUtils.h>
28
29
 
29
30
  namespace Passenger {
30
31
 
@@ -36,7 +37,10 @@ using namespace std;
36
37
 
37
38
  #if defined(__x86_64__) || defined(__x86__)
38
39
  void
39
- convertLowerCase(unsigned char *data, size_t len) {
40
+ convertLowerCase(const unsigned char * restrict data,
41
+ unsigned char * restrict output,
42
+ size_t len)
43
+ {
40
44
  /*
41
45
  * Parts of this function is taken from stringencoders and modified to add
42
46
  * 64-bit support. https://code.google.com/p/stringencoders/
@@ -111,7 +115,8 @@ convertLowerCase(unsigned char *data, size_t len) {
111
115
  const size_t leftover = len % 8;
112
116
  const size_t imax = len / 8;
113
117
  const boost::uint64_t *s = (const boost::uint64_t *) data;
114
- boost::uint64_t *d = (boost::uint64_t *) data;
118
+ boost::uint64_t *d = (boost::uint64_t *) output;
119
+
115
120
  for (i = 0; i != imax; ++i) {
116
121
  eax = s[i];
117
122
  /*
@@ -125,15 +130,15 @@ convertLowerCase(unsigned char *data, size_t len) {
125
130
  }
126
131
 
127
132
  i = imax * 8;
128
- data = (unsigned char *) d;
133
+ output = (unsigned char *) d;
129
134
  switch (leftover) {
130
- case 7: *data++ = (unsigned char) gsToLowerMap[ustr[i++]];
131
- case 6: *data++ = (unsigned char) gsToLowerMap[ustr[i++]];
132
- case 5: *data++ = (unsigned char) gsToLowerMap[ustr[i++]];
133
- case 4: *data++ = (unsigned char) gsToLowerMap[ustr[i++]];
134
- case 3: *data++ = (unsigned char) gsToLowerMap[ustr[i++]];
135
- case 2: *data++ = (unsigned char) gsToLowerMap[ustr[i++]];
136
- case 1: *data++ = (unsigned char) gsToLowerMap[ustr[i]];
135
+ case 7: *output++ = (unsigned char) gsToLowerMap[ustr[i++]];
136
+ case 6: *output++ = (unsigned char) gsToLowerMap[ustr[i++]];
137
+ case 5: *output++ = (unsigned char) gsToLowerMap[ustr[i++]];
138
+ case 4: *output++ = (unsigned char) gsToLowerMap[ustr[i++]];
139
+ case 3: *output++ = (unsigned char) gsToLowerMap[ustr[i++]];
140
+ case 2: *output++ = (unsigned char) gsToLowerMap[ustr[i++]];
141
+ case 1: *output++ = (unsigned char) gsToLowerMap[ustr[i]];
137
142
  case 0: break;
138
143
  }
139
144
  #elif defined(__x86__)
@@ -143,7 +148,7 @@ convertLowerCase(unsigned char *data, size_t len) {
143
148
  const size_t leftover = len % 4;
144
149
  const size_t imax = len / 4;
145
150
  const boost::uint32_t *s = (const boost::uint32_t *) data;
146
- boost::uint32_t *d = (boost::uint32_t *) data;
151
+ boost::uint32_t *d = (boost::uint32_t *) output;
147
152
  for (i = 0; i != imax; ++i) {
148
153
  eax = s[i];
149
154
  /*
@@ -157,11 +162,11 @@ convertLowerCase(unsigned char *data, size_t len) {
157
162
  }
158
163
 
159
164
  i = imax * 4;
160
- data = (unsigned char *) d;
165
+ output = (unsigned char *) d;
161
166
  switch (leftover) {
162
- case 3: *data++ = (unsigned char) gsToLowerMap[ustr[i++]];
163
- case 2: *data++ = (unsigned char) gsToLowerMap[ustr[i++]];
164
- case 1: *data++ = (unsigned char) gsToLowerMap[ustr[i]];
167
+ case 3: *output++ = (unsigned char) gsToLowerMap[ustr[i++]];
168
+ case 2: *output++ = (unsigned char) gsToLowerMap[ustr[i++]];
169
+ case 1: *output++ = (unsigned char) gsToLowerMap[ustr[i]];
165
170
  case 0: break;
166
171
  }
167
172
  #else