passenger 5.0.29 → 5.0.30

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de34a89bcd92faaf4c870691894fdc98545e933f
4
- data.tar.gz: de6ab1650b829f01146d3851f85cc38f347b02f5
3
+ metadata.gz: 722c1e1bd4ec567159a9176ac6ccb0e207f605af
4
+ data.tar.gz: 51d23530f41934e66d5c8a8c13d68386400765fb
5
5
  SHA512:
6
- metadata.gz: fec73a5f401c95111c03dde4e99f2d393d2b340e82ced8e051c11862f8810ca8f9d6b5164701622d6e1e80655f58ac6859297dbff1089f0ae4a7c4a939bcfc35
7
- data.tar.gz: 8aa0e543b0ef031f56ef902f67e6ac6b6e032cf057cac7c9562d21b095d70ad8c14194e278ff692acd5e62a3ae0904f65b1f050946ed0993854e14af1cf8d762
6
+ metadata.gz: 746361cde0146a6ad7ff161553d61eee22889cbf682e45306e1510337d0826957ea6f61b434ca659b450c82b58e8af2ff578ddbdf2297dc937b5adfa14817e8c
7
+ data.tar.gz: afd17292ab8b5764edd39574914817462268fd85293ab49c8ffc7b3a117239726c9817b332bcf9675f0649f88994938e8e5fc9f5dea53ad724f97a621b83cf92
data/CHANGELOG CHANGED
@@ -1,3 +1,12 @@
1
+ Release 5.0.30
2
+ --------------
3
+
4
+ * Changes mbuf block size from 512 to 4096 bytes to better fit modern requests and significantly speed up disk buffering.
5
+ * [Nginx] Fixes PCRE checksum after the preferred version update in 5.0.29 (contributed by: clemensg).
6
+ * [Apache] Fixes buffer limit crash on large file upload (when core disk buffer can't keep up with client for some time), and limits per-client buffer memory usage to 130 KB. Closes GH-1620.
7
+ * Fixes potential hang when an UnseekableSocket gets serialized to json. Closes GH-1838.
8
+
9
+
1
10
  Release 5.0.29
2
11
  --------------
3
12
 
@@ -215,6 +215,7 @@ private:
215
215
  void beginBufferingBody(Client *client, Request *req);
216
216
  Channel::Result whenBufferingBody_onRequestBody(Client *client, Request *req,
217
217
  const MemoryKit::mbuf &buffer, int errcode);
218
+ static void _bodyBufferFlushed(FileBufferedChannel *_channel);
218
219
 
219
220
 
220
221
  /****** Stage: checkout session ******/
@@ -56,6 +56,23 @@ Controller::beginBufferingBody(Client *client, Request *req) {
56
56
  req->beginStopwatchLog(&req->stopwatchLogs.bufferingRequestBody, "buffering request body");
57
57
  }
58
58
 
59
+ /**
60
+ * Relevant when our body data source (bodyChannel) was throttled (by whenBufferingBody_onRequestBody).
61
+ * Called when our data sink (bodyBuffer) in-memory part is drained and ready for more data.
62
+ */
63
+ void
64
+ Controller::_bodyBufferFlushed(FileBufferedChannel *channel) {
65
+ Request *req = static_cast<Request *>(static_cast<
66
+ ServerKit::BaseHttpRequest *>(channel->getHooks()->userData));
67
+
68
+ req->bodyBuffer.clearBuffersFlushedCallback();
69
+ req->bodyChannel.start();
70
+ }
71
+
72
+ /**
73
+ * Receives data (buffer) originating from the bodyChannel, to be passed on to the bodyBuffer.
74
+ * Backpressure is applied when the bodyBuffer in-memory part exceeds a threshold.
75
+ */
59
76
  ServerKit::Channel::Result
60
77
  Controller::whenBufferingBody_onRequestBody(Client *client, Request *req,
61
78
  const MemoryKit::mbuf &buffer, int errcode)
@@ -70,6 +87,15 @@ Controller::whenBufferingBody_onRequestBody(Client *client, Request *req,
70
87
  cEscapeString(StaticString(buffer.start, buffer.size())) <<
71
88
  "\"; " << req->bodyBytesBuffered << " bytes buffered so far");
72
89
  req->bodyBuffer.feed(buffer);
90
+
91
+ if (req->bodyBuffer.passedThreshold()) {
92
+ // Apply backpressure..
93
+ req->bodyChannel.stop();
94
+ // ..until the in-memory part of our bodyBuffer is drained.
95
+ assert(req->bodyBuffer.getBuffersFlushedCallback() == NULL);
96
+ req->bodyBuffer.setBuffersFlushedCallback(_bodyBufferFlushed);
97
+ }
98
+
73
99
  return Channel::Result(buffer.size(), false);
74
100
  } else if (errcode == 0 || errcode == ECONNRESET) {
75
101
  // EOF
@@ -1049,7 +1049,7 @@ Controller::outputBuffersFlushed(Client *client, Request *req) {
1049
1049
  if (!req->ended()) {
1050
1050
  assert(!req->appSource.isStarted());
1051
1051
  SKC_TRACE(client, 2, "Buffered response data has been written to disk. Resuming application socket");
1052
- client->output.setBuffersFlushedCallback(NULL);
1052
+ client->output.clearBuffersFlushedCallback();
1053
1053
  req->appSource.start();
1054
1054
  }
1055
1055
  }
@@ -112,7 +112,7 @@ Controller::onRequestObjectCreated(Client *client, Request *req) {
112
112
  void
113
113
  Controller::deinitializeClient(Client *client) {
114
114
  ParentClass::deinitializeClient(client);
115
- client->output.setBuffersFlushedCallback(NULL);
115
+ client->output.clearBuffersFlushedCallback();
116
116
  client->output.setDataFlushedCallback(getClientOutputDataFlushedCallback());
117
117
  }
118
118
 
@@ -165,6 +165,7 @@ Controller::deinitializeRequest(Client *client, Request *req) {
165
165
  req->appSink.setConsumedCallback(NULL);
166
166
  req->appSink.deinitialize();
167
167
  req->appSource.deinitialize();
168
+ req->bodyBuffer.clearBuffersFlushedCallback();
168
169
  req->bodyBuffer.deinitialize();
169
170
 
170
171
  /***************/
@@ -55,7 +55,7 @@
55
55
  #define DEFAULT_MAX_POOL_SIZE 6
56
56
  #define DEFAULT_MAX_PRELOADER_IDLE_TIME 300
57
57
  #define DEFAULT_MAX_REQUEST_QUEUE_SIZE 100
58
- #define DEFAULT_MBUF_CHUNK_SIZE 512
58
+ #define DEFAULT_MBUF_CHUNK_SIZE 4096
59
59
  #define DEFAULT_NODEJS "node"
60
60
  #define DEFAULT_POOL_IDLE_TIME 300
61
61
  #define DEFAULT_PYTHON "python"
@@ -80,7 +80,7 @@
80
80
  #define PASSENGER_API_VERSION_MAJOR 0
81
81
  #define PASSENGER_API_VERSION_MINOR 3
82
82
  #define PASSENGER_DEFAULT_USER "nobody"
83
- #define PASSENGER_VERSION "5.0.29"
83
+ #define PASSENGER_VERSION "5.0.30"
84
84
  #define POOL_HELPER_THREAD_STACK_SIZE 262144
85
85
  #define PROCESS_SHUTDOWN_TIMEOUT 60
86
86
  #define PROCESS_SHUTDOWN_TIMEOUT_DISPLAY "1 minute"
@@ -443,7 +443,7 @@ private:
443
443
  * mode, the reader is responsible for popping buffers. In the in-file mode, the writer
444
444
  * is responsible for popping buffers (and writing them to the file).
445
445
  */
446
- boost::uint32_t bytesBuffered;
446
+ boost::uint32_t bytesBuffered; // number of bytes buffered in memory
447
447
  MemoryKit::mbuf firstBuffer;
448
448
  deque<MemoryKit::mbuf> moreBuffers;
449
449
 
@@ -1339,12 +1339,18 @@ public:
1339
1339
  * buffers. For example, in case of FileBufferedFdSinkChannel, this event does
1340
1340
  * not imply that all the in-memory buffers have been written to the sink FD.
1341
1341
  * That's what `dataFlushedCallback` is for.
1342
+ *
1343
+ * N.B. this class intentionally doesn't manage buffersFlushedCallback in any way,
1344
+ * the user is responsible for ensuring correctness of the variable's content.
1342
1345
  */
1343
1346
  Callback buffersFlushedCallback;
1344
1347
  /**
1345
1348
  * Called when all buffered data (whether in-memory or on-disk) has been consumed
1346
1349
  * by the data callback. In case of FileBufferedFdSinkChannel, this means that all
1347
1350
  * buffered data has been written out to the sink FD.
1351
+ *
1352
+ * N.B. this class intentionally doesn't manage dataFlushedCallback in any way,
1353
+ * the user is responsible for ensuring correctness of the variable's content.
1348
1354
  */
1349
1355
  Callback dataFlushedCallback;
1350
1356
 
@@ -1546,6 +1552,11 @@ public:
1546
1552
  return buffersFlushedCallback;
1547
1553
  }
1548
1554
 
1555
+ OXT_FORCE_INLINE
1556
+ void clearBuffersFlushedCallback() {
1557
+ buffersFlushedCallback = NULL;
1558
+ }
1559
+
1549
1560
  OXT_FORCE_INLINE
1550
1561
  void setBuffersFlushedCallback(Callback callback) {
1551
1562
  buffersFlushedCallback = callback;
@@ -239,6 +239,11 @@ public:
239
239
  return FileBufferedChannel::getBuffersFlushedCallback();
240
240
  }
241
241
 
242
+ OXT_FORCE_INLINE
243
+ void clearBuffersFlushedCallback() {
244
+ FileBufferedChannel::clearBuffersFlushedCallback();
245
+ }
246
+
242
247
  OXT_FORCE_INLINE
243
248
  void setBuffersFlushedCallback(Callback callback) {
244
249
  FileBufferedChannel::setBuffersFlushedCallback(callback);
@@ -122,6 +122,7 @@ public:
122
122
  // headers is variable, but the number of secure headers is more or less
123
123
  // constant.
124
124
  HeaderTable secureHeaders;
125
+ // HttpServer feeds all body data received via client->input to bodyChannel
125
126
  Channel bodyChannel;
126
127
 
127
128
  union {
@@ -31,13 +31,13 @@ module PhusionPassenger
31
31
 
32
32
  PACKAGE_NAME = 'passenger'
33
33
  # Run 'rake src/cxx_supportlib/Constants.h' after changing this number.
34
- VERSION_STRING = '5.0.29'
34
+ VERSION_STRING = '5.0.30'
35
35
 
36
36
  PREFERRED_NGINX_VERSION = '1.10.1'
37
37
  NGINX_SHA256_CHECKSUM = '1fd35846566485e03c0e318989561c135c598323ff349c503a6c14826487a801'
38
38
 
39
39
  PREFERRED_PCRE_VERSION = '8.39'
40
- PCRE_SHA256_CHECKSUM = '1dd78994c81e44ac41cf30b2a21d4b4cc6d76ccde7fc6e77713ed51d7bddca47'
40
+ PCRE_SHA256_CHECKSUM = 'ccdf7e788769838f8285b3ee672ed573358202305ee361cfec7a4a4fb005bbc7'
41
41
 
42
42
  STANDALONE_INTERFACE_VERSION = 1
43
43
 
@@ -76,7 +76,14 @@ module PhusionPassenger
76
76
  MESSAGE_SERVER_MAX_USERNAME_SIZE = 100
77
77
  MESSAGE_SERVER_MAX_PASSWORD_SIZE = 100
78
78
  POOL_HELPER_THREAD_STACK_SIZE = 1024 * 256
79
- DEFAULT_MBUF_CHUNK_SIZE = 16 * 32
79
+ # Small mbuf sizes avoid memory overhead (up to 1 blocksize per request), but
80
+ # also introduce context switching and smaller transfer writes. The size is picked
81
+ # to balance this out.
82
+ DEFAULT_MBUF_CHUNK_SIZE = 1024 * 4
83
+ # Affects input and output buffering (between app and client). Threshold is picked
84
+ # such that it fits most output (i.e. html page size, not assets), and allows for
85
+ # high concurrency with low mem overhead. On the upload side there is a penalty
86
+ # but there's no real average upload size anyway so we choose mem safety instead.
80
87
  DEFAULT_FILE_BUFFERED_CHANNEL_THRESHOLD = 1024 * 128
81
88
  SERVER_KIT_MAX_SERVER_ENDPOINTS = 4
82
89
 
@@ -275,6 +275,10 @@ module PhusionPassenger
275
275
  return exception.instance_variable_get(:"@from_unseekable_socket") == @socket.object_id
276
276
  end
277
277
 
278
+ def to_hash
279
+ { :socket => "Not JSON Encodable", :eof => @simulate_eof }
280
+ end
281
+
278
282
  private
279
283
  def annotate(exception)
280
284
  exception.instance_variable_set(:"@from_unseekable_socket", @socket.object_id)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passenger
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.29
4
+ version: 5.0.30
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phusion - http://www.phusion.nl/
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-22 00:00:00.000000000 Z
11
+ date: 2016-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake