net: fix ambiguity in EOF handling

`end` MUST always be emitted **before** `close`. However, if a handle
will invoke `uv_close_cb` immediately, or in the same JS tick - `close`
may be emitted first.

PR-URL: https://github.com/nodejs/node/pull/9066
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Ilkka Myller <ilkka.myller@nodefield.com>
This commit is contained in:
Fedor Indutny 2016-10-12 20:39:37 +00:00
Родитель 0ed6338016
Коммит 31196eaa93
2 изменённых файлов: 31 добавлений и 3 удалений

Просмотреть файл

@ -574,14 +574,16 @@ function onread(nread, buffer) {
debug('EOF');
// push a null to signal the end of data.
// Do it before `maybeDestroy` for correct order of events:
// `end` -> `close`
self.push(null);
if (self._readableState.length === 0) {
self.readable = false;
maybeDestroy(self);
}
// push a null to signal the end of data.
self.push(null);
// internal end event so that we know that the actual socket
// is no longer readable, and we can start the shutdown
// procedure. No need to wait for all the data to be consumed.

Просмотреть файл

@ -0,0 +1,26 @@
'use strict';
require('../common');
const assert = require('assert');
const net = require('net');
const uv = process.binding('uv');
const s = new net.Socket({
handle: {
readStart: function() {
process.nextTick(() => this.onread(uv.UV_EOF, null));
},
close: (cb) => process.nextTick(cb)
},
writable: false
});
s.resume();
const events = [];
s.on('end', () => events.push('end'));
s.on('close', () => events.push('close'));
process.on('exit', () => {
assert.deepStrictEqual(events, [ 'end', 'close' ]);
});