From 8b43d3f52dc4a2fc6e72ee21ba97111fa7447b60 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 14 Mar 2016 17:11:07 -0700 Subject: [PATCH] zlib: do not emit event on *Sync() methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Asynchronous functions in `zlib` should not emit the close event. This fixes an issue where asynchronous calls in a for loop could exhaust memory because the pending event prevents the objects from being garbage collected. Fixes: https://github.com/nodejs/node/issues/1668 PR-URL: https://github.com/nodejs/node/pull/5707 Reviewed-By: jasnell - James M Snell Reviewed-By: trevnorris - Trevor Norris Reviewed-By: Сковорода Никита Андреевич --- lib/zlib.js | 19 +++++++++++-------- test/parallel/test-zlib-sync-no-event.js | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 test/parallel/test-zlib-sync-no-event.js diff --git a/lib/zlib.js b/lib/zlib.js index 0028c35d7923eb..79c78ea4a51307 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -454,18 +454,21 @@ Zlib.prototype.flush = function(kind, callback) { }; Zlib.prototype.close = function(callback) { + _close(this, callback); + process.nextTick(emitCloseNT, this); +}; + +function _close(engine, callback) { if (callback) process.nextTick(callback); - if (this._closed) + if (engine._closed) return; - this._closed = true; + engine._closed = true; - this._handle.close(); - - process.nextTick(emitCloseNT, this); -}; + engine._handle.close(); +} function emitCloseNT(self) { self.emit('close'); @@ -535,12 +538,12 @@ Zlib.prototype._processChunk = function(chunk, flushFlag, cb) { } if (nread >= kMaxLength) { - this.close(); + _close(this); throw new RangeError(kRangeErrorMessage); } var buf = Buffer.concat(buffers, nread); - this.close(); + _close(this); return buf; } diff --git a/test/parallel/test-zlib-sync-no-event.js b/test/parallel/test-zlib-sync-no-event.js new file mode 100644 index 00000000000000..81d1ad530de27c --- /dev/null +++ b/test/parallel/test-zlib-sync-no-event.js @@ -0,0 +1,21 @@ +'use strict'; +require('../common'); +const zlib = require('zlib'); +const assert = require('assert'); + +const shouldNotBeCalled = () => { throw new Error('unexpected event'); }; + +const message = 'Come on, Fhqwhgads.'; + +const zipper = new zlib.Gzip(); +zipper.on('close', shouldNotBeCalled); + +const buffer = new Buffer(message); +const zipped = zipper._processChunk(buffer, zlib.Z_FINISH); + +const unzipper = new zlib.Gunzip(); +unzipper.on('close', shouldNotBeCalled); + +const unzipped = unzipper._processChunk(zipped, zlib.Z_FINISH); +assert.notEqual(zipped.toString(), message); +assert.strictEqual(unzipped.toString(), message);