Skip to content

process.stdin example from docs no longer works in node 10 #20503

Description

@apieceofbart

I am running process.stdin example from docs:

process.stdin.setEncoding('utf8');

process.stdin.on('readable', () => {
  const chunk = process.stdin.read();
  if (chunk !== null) {
    process.stdout.write(`data: ${chunk}`);
  }
});

process.stdin.on('end', () => {
  process.stdout.write('end');
});

I expect the same results as in node v9 and below: command line should wait for my input and return it prefixed with data: . Instead, process is closed right away. I believe this is regression as example works fine in node v9 and v8.

(edited by @addaleax: syntax highlighting)

Activity

  1. addaleax commented on May 3, 2018

    @addaleax
    Member

    Bisecting this turned into trisecting, because it seems like we introduced this issue gradually:

    • 1e0f331 made a first change in behaviour for the test case, because now only the first chunk of data is being read before the process exits on its own
    • 0778f79 made the change in behaviour to break this fully. I’m not quite sure (yet) why this is happening, though.

    @nodejs/streams

  2. added
    streamIssues and PRs related to Node.js streams.
    processIssues and PRs related to the process subsystem.
    on May 3, 2018
  3. dmfay commented on May 3, 2018

    @dmfay

    I finally narrowed down the problem I was having with Node 10 and node-pg-query-stream to this and lo and behold someone else had already reported it! What I noticed was that I'd get the first batch of results out of the stream, but then it would abort prematurely without emitting end.

    The commit message for 0778f79 looks at odds with the conditional if (!state.destroyed && (state.length || state.ended)) though -- if it's not supposed to emit readable when the stream has ended, shouldn't it be negating state.ended at minimum? In the testcase accompanying the change it looks like the conditional might be satisfied by state.length.

  4. AyushG3112 commented on May 4, 2018

    @AyushG3112
    Contributor

    Can confirm, Changing the condition to if (!state.destroyed && (state.length || !state.ended)) causes the first chunk of data to be read, after which the process exits (which I suppose is fixed by 4383c0a as @addaleax mentioned)

  5. addaleax commented on May 4, 2018

    @addaleax
    Member

    I think the idea behind (state.length || state.ended) was that we do emit the readable event both for incoming data, and for the end-of-data marker. So readable is supposed to be emitted even if the stream has ended, just not after it has been destroyed.

    /cc @nodejs/streams @mafintosh

  6. mafintosh commented on May 4, 2018

    @mafintosh
    Member
  7. addaleax commented on May 4, 2018

    @addaleax
    Member

    @mafintosh The PR description has a standalone test case, if you want

  8. mafintosh commented on May 4, 2018

    @mafintosh
    Member

    @addaleax ah, didn't see that in the email thread but indeed here.

  9. mcollina commented on May 4, 2018

    @mcollina
    SponsorMember

    See also #20449.

    1e0f331 and 4383c0a should stay in ideally (with a fix if needed).

  10. dmfay commented on May 4, 2018

    @dmfay

    @mafintosh this might be more involved than you're looking for but the problem I was having is reducible to the "fast-reader" test case in https://github.com/brianc/node-pg-query-stream if you check out that repository and run the tests.

  11. klimashkin commented on Jun 22, 2018

    @klimashkin

    Any update on that? It breaks some of our tools in development

  12. lundibundi commented on Jul 6, 2018

    @lundibundi
    Member

    I'd like to work on the issue, I seem to have found the underlying cause and hopefully a correct solution =). Will submit a PR soon.

  13. 26 remaining items

  14. anentropic commented on Apr 7, 2019

    @anentropic
    Contributor

    The docs for this feature still aren't very clear...

    Has anyone tried piping in a file longer than 65536 bytes via stdin?

    The example from the docs shows this code:

    process.stdin.on('readable', () => {
      let chunk;
      // Use a loop to make sure we read all available data.
      while ((chunk = process.stdin.read()) !== null) {
        process.stdout.write(`data: ${chunk}`);
      }
    });

    Note the code comment:

    Use a loop to make sure we read all available data.

    Perhaps it's stupid of me, but I assumed this meant the while loop there would cause it to read all of stdin, so I made some code like:

    process.stdin.on('readable', () => {
      let chunk, chunks, content;
      chunks = [];
      // Use a loop to make sure we read all available data.
      while ((chunk = process.stdin.read()) !== null) {
        chunks.push(chunk);
      }
      content = chunks.join('');
      console.log(content.length);
      render(content);
    });

    What I see from this naïve code though is that my content.length is always 65536, but I know the file is longer than that - what I've got in content is truncated.

    Unfortunately because the code was trying to render(content), exceptions prevented me immediately noticing what actually happens: which is that the on('readable' ...) event handler gets called multiple times... then eventually the end event when there is no more to read.

    So I have to structure the code more like this:

          var chunk, chunks, content;
          chunks = [];
          process.stdin.on('end', () => {
            content = chunks.join('');
            console.error(content.length); // 88106 - yay!
            return content;
          });
          process.stdin.on('readable', function() {
            console.error('READABLE')
            while ((chunk = process.stdin.read()) !== null) {
              chunks.push(chunk);
              console.error('CHUNK')
            }
          });

    This makes perfect sense, but I think something of this behaviour ought to be mentioned in the docs.

    https://nodejs.org/api/process.html#process_process_stdin
    Just says:

    The process.stdin property returns a stream connected to stdin (fd 0). It is a net.Socket (which is a Duplex stream) unless fd 0 refers to a file, in which case it is a Readable stream.

    and the docs for Readable streams waffle on quite a bit but I don't see anything about getting multiple readable events:
    https://nodejs.org/api/stream.html#stream_readable_streams

    I understand from the long discussion in the thread above that what the while loop is really for is to ensure that the stream doesn't end early, if there is initially nothing to read?

    Perhaps this could all be made a bit clearer somehow.

  15. mcollina commented on Apr 8, 2019

    @mcollina
    SponsorMember

    @anentropic I think a PR to improve the docs would be welcomed!

  16. anentropic commented on Apr 9, 2019

    @anentropic
    Contributor

    @mcollina ok no prob, give me a day or two

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues and PRs for confirmed bugs.processIssues and PRs related to the process subsystem.streamIssues and PRs related to Node.js streams.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions