stream: ensure writable.destroy() emits error once
Prevent the `'error'` event from being emitted multiple times if `writable.destroy()` is called with an error before the `_destroy()` callback is called. Emit the first error, discard all others. PR-URL: https://github.com/nodejs/node/pull/26057 Fixes: https://github.com/nodejs/node/issues/26015 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
60aaf2c214
commit
49f1bb9b93
@ -10,10 +10,15 @@ function destroy(err, cb) {
|
||||
if (readableDestroyed || writableDestroyed) {
|
||||
if (cb) {
|
||||
cb(err);
|
||||
} else if (err &&
|
||||
(!this._writableState || !this._writableState.errorEmitted)) {
|
||||
process.nextTick(emitErrorNT, this, err);
|
||||
} else if (err) {
|
||||
if (!this._writableState) {
|
||||
process.nextTick(emitErrorNT, this, err);
|
||||
} else if (!this._writableState.errorEmitted) {
|
||||
this._writableState.errorEmitted = true;
|
||||
process.nextTick(emitErrorNT, this, err);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -31,9 +36,13 @@ function destroy(err, cb) {
|
||||
|
||||
this._destroy(err || null, (err) => {
|
||||
if (!cb && err) {
|
||||
process.nextTick(emitErrorAndCloseNT, this, err);
|
||||
if (this._writableState) {
|
||||
if (!this._writableState) {
|
||||
process.nextTick(emitErrorAndCloseNT, this, err);
|
||||
} else if (!this._writableState.errorEmitted) {
|
||||
this._writableState.errorEmitted = true;
|
||||
process.nextTick(emitErrorAndCloseNT, this, err);
|
||||
} else {
|
||||
process.nextTick(emitCloseNT, this);
|
||||
}
|
||||
} else if (cb) {
|
||||
process.nextTick(emitCloseNT, this);
|
||||
|
@ -152,6 +152,32 @@ const assert = require('assert');
|
||||
assert.strictEqual(write.destroyed, true);
|
||||
}
|
||||
|
||||
{
|
||||
const writable = new Writable({
|
||||
destroy: common.mustCall(function(err, cb) {
|
||||
process.nextTick(cb, new Error('kaboom 1'));
|
||||
}),
|
||||
write(chunk, enc, cb) {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
|
||||
writable.on('close', common.mustCall());
|
||||
writable.on('error', common.expectsError({
|
||||
type: Error,
|
||||
message: 'kaboom 2'
|
||||
}));
|
||||
|
||||
writable.destroy();
|
||||
assert.strictEqual(writable.destroyed, true);
|
||||
assert.strictEqual(writable._writableState.errorEmitted, false);
|
||||
|
||||
// Test case where `writable.destroy()` is called again with an error before
|
||||
// the `_destroy()` callback is called.
|
||||
writable.destroy(new Error('kaboom 2'));
|
||||
assert.strictEqual(writable._writableState.errorEmitted, true);
|
||||
}
|
||||
|
||||
{
|
||||
const write = new Writable({
|
||||
write(chunk, enc, cb) { cb(); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user