diff --git a/src/node_crypto.h b/src/node_crypto.h index 269bccbc03a1d7..692978412fc023 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -198,7 +198,9 @@ class SecureContext : public BaseObject { } inline void Reset() { - env()->isolate()->AdjustAmountOfExternalAllocatedMemory(-kExternalSize); + if (ctx_ != nullptr) { + env()->isolate()->AdjustAmountOfExternalAllocatedMemory(-kExternalSize); + } ctx_.reset(); cert_.reset(); issuer_.reset(); diff --git a/test/parallel/test-gc-tls-external-memory.js b/test/parallel/test-gc-tls-external-memory.js new file mode 100644 index 00000000000000..c19fbbe5088306 --- /dev/null +++ b/test/parallel/test-gc-tls-external-memory.js @@ -0,0 +1,35 @@ +'use strict'; +// Flags: --expose-gc + +// Tests that memoryUsage().external doesn't go negative +// when a lot tls connections are opened and closed + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const net = require('net'); +const tls = require('tls'); + +// Payload doesn't matter. We just need to have the tls +// connection try and connect somewhere. +const yolo = Buffer.alloc(10000).fill('yolo'); +const server = net.createServer(function(socket) { + socket.write(yolo); +}); + +server.listen(0, common.mustCall(function() { + const { port } = server.address(); + let runs = 0; + connect(); + + function connect() { + global.gc(); + assert(process.memoryUsage().external >= 0); + if (runs++ < 512) + tls.connect(port).on('error', connect); + else + server.close(); + } +}));