From 2e59ec0c2d27baa0f0bc140ead72d15b1ed9b29c Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 29 Sep 2017 11:29:58 +0200 Subject: [PATCH] child_process: fix memory leak in .fork() Entries in the `net.Server#_workers` array that is used to track handles sent from the master to workers were not deleted when a worker exited, resulting in a slow but inexorable memory leak. PR-URL: https://github.com/nodejs/node/pull/15679 Fixes: https://github.com/nodejs/node/issues/15651 Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- lib/internal/socket_list.js | 1 + lib/net.js | 4 ++++ test/parallel/test-child-process-fork-net2.js | 1 + 3 files changed, 6 insertions(+) diff --git a/lib/internal/socket_list.js b/lib/internal/socket_list.js index 8aa12d45d4ad5b..dd30e9450950e2 100644 --- a/lib/internal/socket_list.js +++ b/lib/internal/socket_list.js @@ -10,6 +10,7 @@ class SocketListSend extends EventEmitter { super(); this.key = key; this.child = child; + child.once('exit', () => this.emit('exit', this)); } _request(msg, cmd, callback) { diff --git a/lib/net.js b/lib/net.js index 9c426102d6a47e..2069216e0fa5f4 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1665,6 +1665,10 @@ Server.prototype.listenFD = internalUtil.deprecate(function(fd, type) { Server.prototype._setupWorker = function(socketList) { this._usingWorkers = true; this._workers.push(socketList); + socketList.once('exit', (socketList) => { + const index = this._workers.indexOf(socketList); + this._workers.splice(index, 1); + }); }; Server.prototype.ref = function() { diff --git a/test/parallel/test-child-process-fork-net2.js b/test/parallel/test-child-process-fork-net2.js index b893685447191f..2686daccb28639 100644 --- a/test/parallel/test-child-process-fork-net2.js +++ b/test/parallel/test-child-process-fork-net2.js @@ -156,6 +156,7 @@ if (process.argv[2] === 'child') { } process.on('exit', function() { + assert.strictEqual(server._workers.length, 0); assert.strictEqual(disconnected, count); assert.strictEqual(connected, count); });