Skip to content

Commit da5cd2c

Browse files
watsonQard
authored andcommitted
fix: always end transaction when socket is closed prematurely (#1445)
This fixes a race condition that in some cases meant that a request transaction was never ended if the underlying TCP socket was closed by the client and the server didn't discover this in time. Fixes #1411
1 parent 604f464 commit da5cd2c

File tree

2 files changed

+12
-7
lines changed

2 files changed

+12
-7
lines changed

lib/instrumentation/http-shared.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ exports.instrumentRequest = function (agent, moduleName) {
3333
ins.bindEmitter(res)
3434

3535
endOfStream(res, function (err) {
36+
if (trans.ended) return
3637
if (!err) return trans.end()
3738

38-
if (agent._conf.errorOnAbortedRequests && !trans.ended) {
39+
if (agent._conf.errorOnAbortedRequests) {
3940
var duration = trans._timer.elapsed()
4041
if (duration > (agent._conf.abortedErrorThreshold * 1000)) {
4142
agent.captureError('Socket closed with active HTTP request (>' + agent._conf.abortedErrorThreshold + ' sec)', {
@@ -47,9 +48,12 @@ exports.instrumentRequest = function (agent, moduleName) {
4748

4849
// Handle case where res.end is called after an error occurred on the
4950
// stream (e.g. if the underlying socket was prematurely closed)
50-
res.on('prefinish', function () {
51+
const end = res.end
52+
res.end = function () {
53+
const result = end.apply(this, arguments)
5154
trans.end()
52-
})
55+
return result
56+
}
5357
})
5458
}
5559
}

test/instrumentation/modules/http/aborted-requests-enabled.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@ test('client-side abort below error threshold - call end', { timeout: 10000 }, f
3737
var server = http.createServer(function (req, res) {
3838
setTimeout(function () {
3939
clientReq.abort()
40-
setTimeout(function () {
41-
res.write('Hello') // server emits clientError if written in same tick as abort
40+
res.write('sync write')
41+
process.nextTick(function () {
42+
res.write('nextTick write')
4243
setTimeout(function () {
43-
res.end(' World')
44+
res.end('setTimeout write')
4445
}, 10)
45-
}, 10)
46+
})
4647
}, (agent._conf.abortedErrorThreshold * 1000) / 2)
4748
})
4849

0 commit comments

Comments
 (0)