Skip to content

Commit

Permalink
zlib: do not emit event on *Sync() methods
Browse files Browse the repository at this point in the history
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: #1668
PR-URL: #5707
Reviewed-By: jasnell - James M Snell <[email protected]>
Reviewed-By: trevnorris - Trevor Norris <[email protected]>
Reviewed-By: Сковорода Никита Андреевич <[email protected]>
  • Loading branch information
Trott committed Mar 19, 2016
1 parent a53b2ac commit 8b43d3f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 8 deletions.
19 changes: 11 additions & 8 deletions lib/zlib.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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;
}
Expand Down
21 changes: 21 additions & 0 deletions test/parallel/test-zlib-sync-no-event.js
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit 8b43d3f

Please sign in to comment.