| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 6f053a4 commit e0b7963
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -957,7 +957,8 @@ changes: | |||
| 957 | 957 | ||
| 958 | 958 | Destroy the request. Optionally emit an `'error'` event, | |
| 959 | 959 | and emit a `'close'` event. Calling this will cause remaining data | |
| 960 | - in the response to be dropped and the socket to be destroyed. | ||
| 960 | + in the response to be dropped, and the socket to be destroyed if used, | ||
| 961 | + or returned to the corresponding Agent pool otherwise if possible. | ||
| 961 | 962 | ||
| 962 | 963 | See [`writable.destroy()`][] for further details. | |
| 963 | 964 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -999,6 +999,7 @@ function onSocketNT(req, socket, err) { | |||
| 999 | 999 | if (socket) { | |
| 1000 | 1000 | if (!err && req.agent && !socket.destroyed) { | |
| 1001 | 1001 | socket.emit('free'); | |
| 1002 | + socket.removeListener('error', socketErrorListener); | ||
| 1002 | 1003 | } else { | |
| 1003 | 1004 | finished(socket.destroy(err || req[kError]), (er) => { | |
| 1004 | 1005 | if (er?.code === 'ERR_STREAM_PREMATURE_CLOSE') { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,50 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const assert = require('assert'); | ||
| 4 | + const http = require('http'); | ||
| 5 | + const { defaultMaxListeners } = require('events'); | ||
| 6 | + | ||
| 7 | + // Immediately destroying an HTTP request must not leak listeners on the | ||
| 8 | + // freed socket. When sockets are reused via a keep-alive agent leaked | ||
| 9 | + // listeners would accumulate to trigger a MaxListenersExceededWarning. | ||
| 10 | + | ||
| 11 | + // Check we don't get a MaxListenersExceededWarning: | ||
| 12 | + process.on('warning', common.mustNotCall('Unexpected warning emitted')); | ||
| 13 | + | ||
| 14 | + const server = http.createServer(common.mustNotCall()); | ||
| 15 | + | ||
| 16 | + server.listen(0, common.mustCall(() => { | ||
| 17 | + const agent = new http.Agent({ keepAlive: true }); | ||
| 18 | + const port = server.address().port; | ||
| 19 | + | ||
| 20 | + // Count actual socket creations to confirm reuse: | ||
| 21 | + let createSocketCount = 0; | ||
| 22 | + const origCreateSocket = agent.createSocket.bind(agent); | ||
| 23 | + agent.createSocket = function(...args) { | ||
| 24 | + createSocketCount++; | ||
| 25 | + return origCreateSocket(...args); | ||
| 26 | + }; | ||
| 27 | + | ||
| 28 | + function executeHttpGet() { | ||
| 29 | + return new Promise((resolve) => { | ||
| 30 | + const req = http.get({ host: '127.0.0.1', port, agent }); | ||
| 31 | + req.on('error', resolve); | ||
| 32 | + req.on('close', resolve); | ||
| 33 | + req.on('response', common.mustNotCall()); | ||
| 34 | + req.destroy(); | ||
| 35 | + }); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + async function main() { | ||
| 39 | + for (let i = 0; i < defaultMaxListeners + 1; i++) { | ||
| 40 | + await executeHttpGet(); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + assert.strictEqual(createSocketCount, 1); | ||
| 44 | + | ||
| 45 | + server.close(); | ||
| 46 | + agent.destroy(); | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + main().then(common.mustCall()); | ||
| 50 | + })); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments