Skip to content

stdout, stderr and stdin are all Duplex streams but documentation states otherwise #9201

Closed

Description

@yonjah
  • Version: 6.x latest (tested on 6.9.1, 6.8.1)
  • Platform: Linux 3.10.0-327.28.3.el7.x86_64

Documentation define stdin as readable stream and stdout, stderr as writable streams -

https://nodejs.org/api/process.html

The process.stderr property returns a Writable stream equivalent to or associated with stderr (fd 2).
...
The process.stdin property returns a Readable stream equivalent to or associated with stdin (fd 0).
...
The process.stdout property returns a Writable stream equivalent to or associated with stdout (fd 1).

But the actual Implementation is of a Duplex stream -

const Stream = require('stream');
['stdin', 'stdout', 'stderr'].forEach((prop) => {
    ['Duplex', 'Writable', 'Readable'].forEach((instance) => {
        console.log(prop, `is`, instance, process[prop] instanceof Stream[instance]);
    });
});

Using a unidirectional stream seems like the obvious choice but if this is not possible for some reason the documentation should be fixed.

This is a bit more annoying with node 4.x (I checked on v4.6.1) since Duplex stream do not extend Writable ones so this will actually evaluate to false -

process.stdout instanceof Stream.Writable

Documentation doesn't mention stream type for v4.x but if the type cannot be changed from Duplex maybe it should mention that since this can cause some confusion

Activity

  1. added
    processIssues and PRs related to the process subsystem.
    on Oct 20, 2016
  2. mscdex commented on Oct 20, 2016

    @mscdex
    Contributor

    FWIW the reason for this is that the process.stdin/stdout/stderr are actually net.Socket objects, which are Duplex streams. You can see this by inspecting process.stdin.constructor for example.

  3. Fishrock123 commented on Oct 20, 2016

    @Fishrock123
    Contributor

    I'd say this is probably just a bug in the inheritance chain of Duplex streams prior to v6.8.0.

  4. addaleax commented on Oct 20, 2016

    @addaleax
    Member

    Using a unidirectional stream seems like the obvious choice but if this is not possible for some reason the documentation should be fixed.

    We currently don’t actually check whether the FDs 0, 1, 2 are readable/writable, and there’s no reason why they can’t be both (e.g. for TTYs or in child processes spawned by node), so keeping it to a generic socket is probably okay.

    (This also means that the .readable and .writable properties of stdio streams may be lying. Sigh.)

  5. added
    docIssues and PRs related to Node.js documentation.
    on Oct 20, 2016
  6. princejwesley commented on Oct 20, 2016

    @princejwesley
    Contributor

    @addaleax I doubt that, In the REPL case (#9189), underlying Input stream is read-only in windows.

  7. addaleax commented on Oct 20, 2016

    @addaleax
    Member

    Yeah, I wouldn’t count the Windows console as a real TTY. ;)

  8. yonjah commented on Oct 20, 2016

    @yonjah
    Author

    @addaleax I don't know enough about node or linux internals but I didn't think a process could write to its own stdin.
    I understand that with child process you want to write into the child.stdin but from the child process,stdin should still only be readable no ?

  9. addaleax commented on Oct 20, 2016

    @addaleax
    Member

    I don't know enough about node or linux internals but I didn't think a process could write to its own stdin.

    If you’re e.g. just running node some-file.js in a POSIX terminal, the FDs 0, 1 and 2 will be indistinguishable references to the TTY – you can read from and write to any of them, each time with the same effect (which is one of the reasons why stderr and stdout can interleave in your terminal, btw). And r/w to any of them is technically supported on Node’s side, too, because the TTY streams inherit from net.Socket. As you may guess, this breaks down as soon as you redirect stdout to a file, for example.

    I understand that with child process you want to write into the child.stdin but from the child process,stdin should still only be readable no ?

    When you specify pipe to child_process.spawn on POSIX, you get a socket pair (there’s been a thread in nodejs/help with a bit more detail).

    I guess it’s weird that you can write to stdin, but it may start to make sense once you think about it – Node doesn’t really give you any way to specify whether the child process should see the readable end or the writable end of a pipe.

  10. bnoordhuis commented on Oct 20, 2016

    @bnoordhuis
    Member

    Actually, I'm not sure if writing to process.stdin still works the way it used to. It looks like commit 9ae1a61 from March last year put a stop to that. It's arguably a kind of regression because a snippet like below used to work in older versions of node:

    var spawn = require('child_process').spawn;
    var args = ['-e', 'process.stdin.write("ok\\n")'];
    var proc = spawn(process.execPath, args, { stdio: ['pipe'] });
    proc.stdin.pipe(process.stdout);

    I'll file an issue.

    EDIT: Fixed copy/paste error in example.

  11. yonjah commented on Oct 21, 2016

    @yonjah
    Author

    @bnoordhuis @addaleax Can you give a semi real example where this might actually be used ?

  12. addaleax commented on Oct 21, 2016

    @addaleax
    Member

    @yonjah I’ve never seen something like that in the wild, no (well, at least not done intentionally 😄).

    I’d say it’s more that there’s no real reason to treat the stdio FDs different from other FDs.

  13. yonjah commented on Oct 22, 2016

    @yonjah
    Author

    @addaleax So maybe it's a good ides to have them as a unidirection
    streams and throwing an error if someone tries to write to stdin or read from stdout.
    So if anyone makes such a mistake it will be caught quickly.

    If someone has an actual need to write to stdin I guess they can always create a custom stream using the file descriptor.

    Though I don't know if this is actually possible with the current net.Socket implementation

  14. princejwesley commented on Oct 22, 2016

    @princejwesley
    Contributor

    @yonjah we write to stdin in unit tests.

  15. addaleax commented on Oct 23, 2016

    @addaleax
    Member

    @yonjah I think I generally agree with you, but more in a “maybe Node should have done this differently from the beginning” kind of way. To break this now does not sound like it’s worth the breakage to me, even if there is only a very small amount of it.

  16. 3 remaining items

  17. fhinkel commented on Mar 27, 2017

    @fhinkel
    Contributor

    Thanks, landed in 1005b1d

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

    docIssues and PRs related to Node.js documentation.good first issueIssues that are suitable for first-time contributors.processIssues and PRs related to the process subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions