Skip to content

Commit 69a7b68

Browse files
authored
fix: always end transaction when socket is closed prematurely (#1439)
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 a429699 commit 69a7b68

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
@@ -35,9 +35,10 @@ exports.instrumentRequest = function (agent, moduleName) {
3535
ins.bindEmitter(res)
3636

3737
endOfStream(res, function (err) {
38+
if (trans.ended) return
3839
if (!err) return trans.end()
3940

40-
if (agent._conf.errorOnAbortedRequests && !trans.ended) {
41+
if (agent._conf.errorOnAbortedRequests) {
4142
var duration = trans._timer.elapsed()
4243
if (duration > (agent._conf.abortedErrorThreshold * 1000)) {
4344
agent.captureError('Socket closed with active HTTP request (>' + agent._conf.abortedErrorThreshold + ' sec)', {
@@ -49,9 +50,12 @@ exports.instrumentRequest = function (agent, moduleName) {
4950

5051
// Handle case where res.end is called after an error occurred on the
5152
// stream (e.g. if the underlying socket was prematurely closed)
52-
res.on('prefinish', function () {
53+
const end = res.end
54+
res.end = function () {
55+
const result = end.apply(this, arguments)
5356
trans.end()
54-
})
57+
return result
58+
}
5559
})
5660
}
5761
}

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)