Skip to content

[REG 20.9->20.10] stream: Pipe is stopped after error on another pipe from the same source #53185

Open
@orgads

Description

@orgads

Version

20.13.1

Platform

Microsoft Windows NT 10.0.19045.0 x64

Subsystem

stream

What steps will reproduce the bug?

import assert from 'assert';
import stream from 'stream';

class SizeCounter extends stream.Writable {
  constructor(name, fail) {
    super();
    this.totalSize = 0;
    this.name = name;
    this.fail = fail;
  }

  _write(chunk, _encoding, callback) {
    this.totalSize += chunk.length;
    console.log(this.name, this.totalSize);
    if (this.fail)
      return callback(new Error('You asked me to fail'));
    return callback();
  }

  _final(callback) {
    console.log(`${this.name} Total size: ${this.totalSize}`);
    callback();
  }
}

const src = new stream.PassThrough();
const dst1 = new SizeCounter('1', true);
const dst2 = new SizeCounter('2', false);

src.write(Buffer.alloc(20000));
src.write(Buffer.alloc(20000));
src.end();

dst1.on('error', () => {
  // uncomment as a workaround
  // src.resume();
});

stream.finished(src, () => console.log('src ended'));
stream.finished(dst1, (err) => console.log('dst1 ended', err?.message));
stream.finished(dst2, (err) => console.log('dst2 ended', err?.message));

src.pipe(dst1, { end: true });
src.pipe(dst2, { end: true });
setImmediate(() => assert.strictEqual(dst2.totalSize, 40000));

Output with 20.9.0:

1 20000
2 20000
dst1 ended You asked me to fail
2 40000
2 Total size: 40000
src ended
dst2 ended undefined

Output with 20.10.0:

1 20000
2 20000
dst1 ended You asked me to fail
node:assert:125
  throw new AssertionError(obj);
  ^

AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

20000 !== 40000

    at Immediate._onImmediate (file:///home/orgads/test/test.mjs:45:27)
    at process.processImmediate (node:internal/timers:478:21) {
  generatedMessage: true,
  code: 'ERR_ASSERTION',
  actual: 20000,
  expected: 40000,
  operator: 'strictEqual'
}

Node.js v20.10.0

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior? Why is that the expected behavior?

I expect the stream to keep draining (at least when it still has listeners to data).

What do you see instead?

The stream is paused.

Additional information

Bisected to #50014.

Related bug:

Metadata

Metadata

Assignees

No one assigned

    Labels

    regressionIssues related to regressions.streamIssues and PRs related to the stream subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions