Repository navigation
No finish/close event on aborted http-response - race condition #1309
Copy link
Copy link
Closed
Labels
confirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.httpIssues and PRs related to the http subsystem.Issues and PRs related to the http subsystem.
Description
When tracking requests of a HTTP-Server - with server.on('request') and res.on('finish', ...) or res.on('close', ...) - we noticed inconsistent results over time (requests that are never finished or closed).
We tracked this race condition down to the following reproducable test case:
- connection is aborted from client side
- socket gets destroyed (but socket-"close"-event still not delivered)
- trying to send response
- socket-"close" event delivered
-> No "close" and no "finish" event on response!
var common = require('../common');
var assert = require('assert');
var http = require('http');
var clientRequest = null;
var serverResponseFinishedOrClosed = 0;
var server = http.createServer(function (req, res) {
console.log('server: request');
res.on('finish', function () {
console.log('server: response finish');
serverResponseFinishedOrClosed++;
});
res.on('close', function () {
console.log('server: response close');
serverResponseFinishedOrClosed++;
});
console.log('client: aborting request');
clientRequest.abort();
setImmediate(function() {
console.log('server: tick 1' + (req.connection.destroyed ? ' (connection destroyed!)' : ''));
setImmediate(function () {
console.log('server: tick 2' + (req.connection.destroyed ? ' (connection destroyed!)' : ''));
console.log('server: sending response');
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Response\n');
console.log('server: res.end() returned');
setImmediate(function () {
server.close();
});
});
});
});
server.on('listening', function () {
console.log('server: listening on port ' + common.PORT);
console.log('client: starting request');
var options = {port: common.PORT, path: '/'};
clientRequest = http.get(options, function () {});
clientRequest.on('error', function () {});
});
server.on('connection', function (connection) {
console.log('server: connection');
connection.on('close', function () { console.log('server: connection close'); });
});
server.on('close', function () {
console.log('server: close');
assert.equal(serverResponseFinishedOrClosed, 1, 'Expected either one "finish" or one "close" event on the response for aborted connections (got ' + serverResponseFinishedOrClosed + ')');
});
server.listen(common.PORT);- With one more
setImmediate()call, you get a response close event (which is fine) - With one less
setImmediate()call, you get a response finish event (which is fine) - Reproducable with io.js 1.6.3, io.js 1.3.0, io.js 1.1.0, node 0.12.0
- In node 0.10 the race-condition was different: This test case works fine, but with one more
setImmediate(), two events are delivered (finish AND close)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
confirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.httpIssues and PRs related to the http subsystem.Issues and PRs related to the http subsystem.
Activity
not-implemented commentedon Apr 1, 2015
The different behaviour between node 0.10 (<=0.11.5) and node 0.12 (>=0.11.6) may be related to the changes made by @isaacs ("http: Consistent 'finish' event semantics", 7c9b607, and "http: Add write()/end() callbacks" da93d6a).
Olegas commentedon Apr 1, 2015
+1
Can see this happens sometimes.
Neither
finishnorcloseevent is triggered onres. Stable reproduces in our environment, we can see this graphically (we count "active" connections withfinish/closeevents).not-implemented commentedon Apr 8, 2015
Proposed fix see pull request #1373
Fishrock123 commentedon Apr 17, 2015
#1411
brendanashworth commentedon May 14, 2015
The fix for this (#1411, semver-major) is now on track for the 3.0.0 release.
KoltesDigital commentedon Aug 13, 2015
Could it please be released earlier? I'm afraid 3.0.0 won't come soon.
Fishrock123 commentedon Aug 13, 2015
3.0.0 is out and this landed in it. :) https://iojs.org/dist/v3.0.0/
Update NodeJS to 4.x
evantahler commentedon May 20, 2016
I've found something similar here, which you can emulate with node v4 and v5... just by sending the
Content-Lengthheader.https://gist.github.com/evantahler/2f6c4241c47d7c89f5555d833475c8b8