Skip to content

stream: non-readable Duplex async construct race condition #34448

@jasnell

Description

@jasnell

@nodejs/streams @ronag

Try..

const { Duplex } = require('stream');

class M extends Duplex {
  constructor() {
    super({ readable: false });
  }

  _construct(callback) {
    setTimeout(() => {
      console.log(1);
      callback();
    }, 2000);
  }

  _write(chunk, encoding, callback) {
    console.log(chunk.toString());
    callback();
  }

  _read() {
    this.push(null);
  }
}

const m = new M();
m.resume();
m.end('foo');
m.on('close', () => console.log('destroyed'));

Outputs:

foo
destroyed
1

Note that the auto-destruction of the Duplex does not appropriately wait for the completion of the async _construct(). Changing the construction options to { readable: true } causes the code to work as expected:

const { Duplex } = require('stream');

class M extends Duplex {
  constructor() {
    super({ readable: true});
  }

  _construct(callback) {
    setTimeout(() => {
      console.log(1);
      callback();
    }, 2000);
  }

  _write(chunk, encoding, callback) {
    console.log(chunk.toString());
    callback();
  }

  _read() {
    this.push(null);
  }
}

const m = new M();
m.resume();
m.end('foo');
m.on('close', () => console.log('destroyed'));

Outputs:

foo
1
destroyed

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues with confirmed bugs.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