Skip to content

Commit 23d92ec

Browse files
Eran Hammerisaacs
Eran Hammer
authored andcommitted
stream: Fix double pipe error emit
If an error listener is added to a stream using once() before it is piped, it is invoked and removed during pipe() but before pipe() sees it which causes it to be emitted again. Fixes #4155 #4978
1 parent 366baed commit 23d92ec

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

lib/_stream_readable.js

100644100755
+3-1
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,11 @@ Readable.prototype.pipe = function(dest, pipeOpts) {
511511

512512
// if the dest has an error, then stop piping into it.
513513
// however, don't suppress the throwing behavior for this.
514+
// check for listeners before emit removes one-time listeners.
515+
var errListeners = EE.listenerCount(dest, 'error');
514516
function onerror(er) {
515517
unpipe();
516-
if (EE.listenerCount(dest, 'error') === 0)
518+
if (errListeners === 0 && EE.listenerCount(dest, 'error') === 0)
517519
dest.emit('error', er);
518520
}
519521
dest.once('error', onerror);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
23+
var common = require('../common.js');
24+
var assert = require('assert');
25+
26+
var util = require('util');
27+
var stream = require('stream');
28+
29+
30+
var Read = function() {
31+
stream.Readable.call(this);
32+
};
33+
util.inherits(Read, stream.Readable);
34+
35+
Read.prototype._read = function(size) {
36+
this.push('x');
37+
this.push(null);
38+
};
39+
40+
41+
var Write = function() {
42+
stream.Writable.call(this);
43+
};
44+
util.inherits(Write, stream.Writable);
45+
46+
Write.prototype._write = function(buffer, encoding, cb) {
47+
this.emit('error', new Error('boom'));
48+
this.emit('alldone');
49+
};
50+
51+
var read = new Read();
52+
var write = new Write();
53+
54+
write.once('error', function(err) {});
55+
write.once('alldone', function(err) {
56+
console.log('ok');
57+
});
58+
59+
process.on('exit', function(c) {
60+
console.error('error thrown even with listener');
61+
});
62+
63+
read.pipe(write);
64+

0 commit comments

Comments
 (0)