From 0e89b64d6606d9c7948259e9090a46d185c5281f Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 24 Dec 2019 16:22:39 +0100 Subject: [PATCH] zlib: allow writes after readable 'end' to finish Call the callback for writes that occur after the stream is closed. This also requires changes to the code to not call `.destroy()` on the stream in `.on('end')`, and to ignore chunks written afterwards. Previously, these writes would just queue up silently, as their `_write()` callback would never have been called. Fixes: https://github.com/nodejs/node/issues/30976 PR-URL: https://github.com/nodejs/node/pull/31082 Reviewed-By: Denys Otrishko Reviewed-By: Luigi Pinca Reviewed-By: Ben Noordhuis Reviewed-By: Rich Trott Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- lib/zlib.js | 13 +++++-------- test/parallel/test-zlib-write-after-end.js | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 test/parallel/test-zlib-write-after-end.js diff --git a/lib/zlib.js b/lib/zlib.js index 3b9e522a06c7e5..e85cfa9b1f1b5c 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -275,7 +275,7 @@ function ZlibBase(opts, mode, handle, { flush, finishFlush, fullFlush }) { this._defaultFlushFlag = flush; this._finishFlushFlag = finishFlush; this._defaultFullFlushFlag = fullFlush; - this.once('end', this.close); + this.once('end', _close.bind(null, this)); this._info = opts && opts.info; } ObjectSetPrototypeOf(ZlibBase.prototype, Transform.prototype); @@ -487,7 +487,7 @@ function processChunkSync(self, chunk, flushFlag) { function processChunk(self, chunk, flushFlag, cb) { const handle = self._handle; - assert(handle, 'zlib binding closed'); + if (!handle) return process.nextTick(cb); handle.buffer = chunk; handle.cb = cb; @@ -513,13 +513,9 @@ function processCallback() { const self = this[owner_symbol]; const state = self._writeState; - if (self._hadError) { - this.buffer = null; - return; - } - - if (self.destroyed) { + if (self._hadError || self.destroyed) { this.buffer = null; + this.cb(); return; } @@ -539,6 +535,7 @@ function processCallback() { } if (self.destroyed) { + this.cb(); return; } diff --git a/test/parallel/test-zlib-write-after-end.js b/test/parallel/test-zlib-write-after-end.js new file mode 100644 index 00000000000000..2b31ff30dc8591 --- /dev/null +++ b/test/parallel/test-zlib-write-after-end.js @@ -0,0 +1,16 @@ +'use strict'; +const common = require('../common'); +const zlib = require('zlib'); + +// Regression test for https://github.com/nodejs/node/issues/30976 +// Writes to a stream should finish even after the readable side has been ended. + +const data = zlib.deflateRawSync('Welcome'); + +const inflate = zlib.createInflateRaw(); + +inflate.resume(); +inflate.write(data, common.mustCall()); +inflate.write(Buffer.from([0x00]), common.mustCall()); +inflate.write(Buffer.from([0x00]), common.mustCall()); +inflate.flush(common.mustCall());