tls: do not rely on 'drain' handlers in StreamWrap

`'drain'` event handlers may not be invoked if the stream
is currently finishing. Instead, use the fact that we know
when writes are active or not, and invoke the delayed shutdown
handler from our own after-write callback.

PR-URL: https://github.com/nodejs/node/pull/24290
Refs: https://github.com/nodejs/node/pull/24288
Refs: https://github.com/nodejs/node/pull/24075
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Reviewed-By: Ouyang Yadong <oyydoibh@gmail.com>
This commit is contained in:
Anna Henningsen 2018-11-10 21:09:42 +01:00
parent 62d053b707
commit cbbf64e40e
No known key found for this signature in database
GPG Key ID: 9C63F3A6CD2AD8F9

View File

@ -11,6 +11,7 @@ const { ERR_STREAM_WRAP } = require('internal/errors').codes;
const kCurrentWriteRequest = Symbol('kCurrentWriteRequest');
const kCurrentShutdownRequest = Symbol('kCurrentShutdownRequest');
const kPendingShutdownRequest = Symbol('kPendingShutdownRequest');
function isClosing() { return this[owner_symbol].isClosing(); }
function onreadstart() { return this[owner_symbol].readStart(); }
@ -79,6 +80,7 @@ class JSStreamWrap extends Socket {
this.stream = stream;
this[kCurrentWriteRequest] = null;
this[kCurrentShutdownRequest] = null;
this[kPendingShutdownRequest] = null;
this.readable = stream.readable;
this.writable = stream.writable;
@ -115,8 +117,10 @@ class JSStreamWrap extends Socket {
// Working around that on the native side is not quite trivial (yet?),
// so for now that is supported here.
if (this[kCurrentWriteRequest] !== null)
return this.once('drain', () => this.doShutdown(req));
if (this[kCurrentWriteRequest] !== null) {
this[kPendingShutdownRequest] = req;
return 0;
}
assert.strictEqual(this[kCurrentWriteRequest], null);
assert.strictEqual(this[kCurrentShutdownRequest], null);
this[kCurrentShutdownRequest] = req;
@ -189,6 +193,11 @@ class JSStreamWrap extends Socket {
this[kCurrentWriteRequest] = null;
handle.finishWrite(req, errCode);
if (this[kPendingShutdownRequest]) {
const req = this[kPendingShutdownRequest];
this[kPendingShutdownRequest] = null;
this.doShutdown(req);
}
}
doClose(cb) {