From 6fce1a314ed008223fb5e6bc5b8e3252e7ca7238 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Mon, 17 Jul 2017 19:25:21 +0200 Subject: [PATCH 1/4] zlib: check if the stream is destroyed before push If the stream is destroyed while the transform is still being applied, push() should not be called, and the internal state should be cleared. Refs: https://github.com/koajs/compress/issues/60 PR-URL: https://github.com/nodejs/node/pull/14330 Backport-PR-URL: https://github.com/nodejs/node/pull/14396 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Conflicts: lib/zlib.js --- lib/zlib.js | 3 +++ test/parallel/test-zlib-destroy-pipe.js | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 test/parallel/test-zlib-destroy-pipe.js diff --git a/lib/zlib.js b/lib/zlib.js index a25901ac6ef16d..d620b6bee3470a 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -431,6 +431,9 @@ Zlib.prototype._processChunk = function _processChunk(chunk, flushFlag, cb) { if (self._hadError) return; + if (self.destroyed) + return; + var have = availOutBefore - availOutAfter; assert(have >= 0, 'have should not go down'); diff --git a/test/parallel/test-zlib-destroy-pipe.js b/test/parallel/test-zlib-destroy-pipe.js new file mode 100644 index 00000000000000..38b8a5b4926e51 --- /dev/null +++ b/test/parallel/test-zlib-destroy-pipe.js @@ -0,0 +1,21 @@ +'use strict'; + +const common = require('../common'); +const zlib = require('zlib'); +const { Writable } = require('stream'); + +// verify that the zlib transform does not error in case +// it is destroyed with data still in flight + +const ts = zlib.createGzip(); + +const ws = new Writable({ + write: common.mustCall((chunk, enc, cb) => { + setImmediate(cb); + ts.destroy(); + }) +}); + +const buf = Buffer.allocUnsafe(1024 * 1024 * 20); +ts.end(buf); +ts.pipe(ws); From 302c19b00655e5629654bf0ec25a05650e2bd473 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Thu, 20 Jul 2017 12:08:35 +0200 Subject: [PATCH 2/4] process: triggerAsyncId can be undefined Fixes: https://github.com/nodejs/node/issues/14386 Fixes: https://github.com/nodejs/node/issues/14381 PR-URL: https://github.com/nodejs/node/pull/14387 Reviewed-By: Refael Ackermann Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Trevor Norris --- lib/internal/process/next_tick.js | 2 +- .../test-internal-nexttick-default-trigger.js | 5 +++ .../test-http-outgoing-message-inheritance.js | 32 +++++++++++++++++++ .../test-http-server-response-standalone.js | 27 ++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-http-outgoing-message-inheritance.js create mode 100644 test/parallel/test-http-server-response-standalone.js diff --git a/lib/internal/process/next_tick.js b/lib/internal/process/next_tick.js index e458ba6e5eb748..48a8b4a4b8fd81 100644 --- a/lib/internal/process/next_tick.js +++ b/lib/internal/process/next_tick.js @@ -281,7 +281,7 @@ function setupNextTick() { if (process._exiting) return; - if (triggerAsyncId === null) { + if (!Number.isSafeInteger(triggerAsyncId) || triggerAsyncId <= 0) { triggerAsyncId = async_hooks.initTriggerId(); } diff --git a/test/async-hooks/test-internal-nexttick-default-trigger.js b/test/async-hooks/test-internal-nexttick-default-trigger.js index 90e566b7063c46..5bd38c8a3a66a0 100644 --- a/test/async-hooks/test-internal-nexttick-default-trigger.js +++ b/test/async-hooks/test-internal-nexttick-default-trigger.js @@ -26,6 +26,11 @@ internal.nextTick(null, common.mustCall(function() { assert.strictEqual(async_hooks.triggerAsyncId(), rootAsyncId); })); +// internal default +internal.nextTick(undefined, common.mustCall(function() { + assert.strictEqual(async_hooks.triggerAsyncId(), rootAsyncId); +})); + // internal internal.nextTick(rootAsyncId + 1, common.mustCall(function() { assert.strictEqual(async_hooks.triggerAsyncId(), rootAsyncId + 1); diff --git a/test/parallel/test-http-outgoing-message-inheritance.js b/test/parallel/test-http-outgoing-message-inheritance.js new file mode 100644 index 00000000000000..05a241dc8bda00 --- /dev/null +++ b/test/parallel/test-http-outgoing-message-inheritance.js @@ -0,0 +1,32 @@ +'use strict'; + +const common = require('../common'); +const { OutgoingMessage } = require('http'); +const { Writable } = require('stream'); +const assert = require('assert'); + +// check that OutgoingMessage can be used without a proper Socket +// Fixes: https://github.com/nodejs/node/issues/14386 +// Fixes: https://github.com/nodejs/node/issues/14381 + +class Response extends OutgoingMessage { + constructor() { + super({ method: 'GET', httpVersionMajor: 1, httpVersionMinor: 1 }); + } + + _implicitHeader() {} +} + +const res = new Response(); +const ws = new Writable({ + write: common.mustCall((chunk, encoding, callback) => { + assert(chunk.toString().match(/hello world/)); + setImmediate(callback); + }) +}); + +res.socket = ws; +ws._httpMessage = res; +res.connection = ws; + +res.end('hello world'); diff --git a/test/parallel/test-http-server-response-standalone.js b/test/parallel/test-http-server-response-standalone.js new file mode 100644 index 00000000000000..7025c734b3103d --- /dev/null +++ b/test/parallel/test-http-server-response-standalone.js @@ -0,0 +1,27 @@ +'use strict'; + +const common = require('../common'); +const { ServerResponse } = require('http'); +const { Writable } = require('stream'); +const assert = require('assert'); + +// check that ServerResponse can be used without a proper Socket +// Fixes: https://github.com/nodejs/node/issues/14386 +// Fixes: https://github.com/nodejs/node/issues/14381 + +const res = new ServerResponse({ + method: 'GET', + httpVersionMajor: 1, + httpVersionMinor: 1 +}); + +const ws = new Writable({ + write: common.mustCall((chunk, encoding, callback) => { + assert(chunk.toString().match(/hello world/)); + setImmediate(callback); + }) +}); + +res.assignSocket(ws); + +res.end('hello world'); From 8d426bbeec12d1ca41fc1be4724e464a82478c15 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Thu, 20 Jul 2017 18:02:54 +0200 Subject: [PATCH 3/4] http: do not abort if socket is missing Fixes: https://github.com/nodejs/node/issues/14368 PR-URL: https://github.com/nodejs/node/pull/14387 Reviewed-By: Refael Ackermann Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Trevor Norris --- lib/_http_outgoing.js | 2 +- .../test-http-server-write-after-end.js | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-http-server-write-after-end.js diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index b6598f0c17036f..31973fceadb6b8 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -633,7 +633,7 @@ OutgoingMessage.prototype.write = function write(chunk, encoding, callback) { function write_(msg, chunk, encoding, callback, fromEnd) { if (msg.finished) { var err = new Error('write after end'); - nextTick(msg.socket[async_id_symbol], + nextTick(msg.socket && msg.socket[async_id_symbol], writeAfterEndNT.bind(msg), err, callback); diff --git a/test/parallel/test-http-server-write-after-end.js b/test/parallel/test-http-server-write-after-end.js new file mode 100644 index 00000000000000..045cdcf4b75afb --- /dev/null +++ b/test/parallel/test-http-server-write-after-end.js @@ -0,0 +1,27 @@ +'use strict'; + +const common = require('../common'); +const http = require('http'); +const assert = require('assert'); + +// Fix for https://github.com/nodejs/node/issues/14368 + +const server = http.createServer(handle); + +function handle(req, res) { + res.on('error', common.mustCall((err) => { + assert.strictEqual(err.message, 'write after end'); + server.close(); + })); + + res.write('hello'); + res.end(); + + setImmediate(common.mustCall(() => { + res.write('world'); + })); +} + +server.listen(0, common.mustCall(() => { + http.get(`http://localhost:${server.address().port}`); +})); From 7e463500b2483c084d1dbc016806d6f1092ddabf Mon Sep 17 00:00:00 2001 From: Jeremiah Senkpiel Date: Thu, 20 Jul 2017 13:52:31 -0400 Subject: [PATCH 4/4] 2017-07-20, Version 8.2.1 (Current) Notable changes * http: Writes no longer abort if the Socket is missing. * process, async_hooks: Avoid problems when triggerAsyncId is undefined. * zlib: Streams no longer attempt to process data when destroyed. PR-URL: https://github.com/nodejs/node/pull/14399 --- CHANGELOG.md | 3 ++- doc/changelogs/CHANGELOG_V8.md | 16 ++++++++++++++++ src/node_version.h | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4caef61079be79..ab0fd9875432ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,8 @@ release. -8.2.0
+8.2.1
+8.2.0
8.1.4
8.1.3
8.1.2
diff --git a/doc/changelogs/CHANGELOG_V8.md b/doc/changelogs/CHANGELOG_V8.md index 1d01b6ebd3eea1..c1f6b7f9c300a3 100644 --- a/doc/changelogs/CHANGELOG_V8.md +++ b/doc/changelogs/CHANGELOG_V8.md @@ -6,6 +6,7 @@ +8.2.1
8.2.0
8.1.4
8.1.3
@@ -27,6 +28,21 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + +## 2017-07-20, Version 8.2.1 (Current), @fishrock123 + +### Notable changes + +* **http**: Writes no longer abort if the Socket is missing. +* **process, async_hooks**: Avoid problems when `triggerAsyncId` is `undefined`. +* **zlib**: Streams no longer attempt to process data when destroyed. + +### Commits + +* [[`8d426bbeec`](https://github.com/nodejs/node/commit/8d426bbeec)] - **http**: do not abort if socket is missing (Matteo Collina) [#14387](https://github.com/nodejs/node/pull/14387) +* [[`302c19b006`](https://github.com/nodejs/node/commit/302c19b006)] - **process**: triggerAsyncId can be undefined (Matteo Collina) [#14387](https://github.com/nodejs/node/pull/14387) +* [[`6fce1a314e`](https://github.com/nodejs/node/commit/6fce1a314e)] - **zlib**: check if the stream is destroyed before push (Matteo Collina) [#14330](https://github.com/nodejs/node/pull/14330) + ## 2017-07-19, Version 8.2.0 (Current), @fishrock123 diff --git a/src/node_version.h b/src/node_version.h index 4fbeac60e805f4..c776f61e26475b 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -26,7 +26,7 @@ #define NODE_MINOR_VERSION 2 #define NODE_PATCH_VERSION 1 -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)