Skip to content

Node ignoring redirections when redirected to a tty #4222

Description

@ELLIOTTCABLE

So, although redirects to other active file-descriptors work as expected, as do redirections to files and the /dev/null device, I cannot redirect successfully to a different tty:

$ node -e 'process.stdout.write("wtf!\n")' 1>/dev/ttys014
wtf!

Example:

# First term:                                                           │# Second term:
                                                                        │
$ tty                                                                   │$ tty
/dev/ttys013                                                            │/dev/ttys014
$ echo 'abc' 1>/dev/ttys014                                             │$ cat
$ ruby -e '$stdout.puts "okay"' 1>/dev/ttys014                          │abc
$ node -e 'process.stdout.write("wtf!\n")' 1>/dev/ttys014               │okay
wtf!                                                                    │
$ node -e 'process.stdout.write("this works\n")' 1>/dev/null            │
$ node -e 'process.stdout.write("this too\n")' 1>output                 │
$ cat output                                                            │
this too                                                                │

Environment:

System: Mac OS X El Capitan 10.11.1
Shell: Zsh 5.1.1 (x86_64-apple-darwin15.0.0)
Node: v4.2.3

Activity

  1. ljharb commented on Dec 10, 2015

    @ljharb
    SponsorMember

    I've reproduced the same thing on Yosemite in stock bash, in node v5.1.1.

  2. kzc commented on Dec 10, 2015

    @kzc

    This behavior is due to uv_tty_init

    /* Reopen the file descriptor when it refers to a tty. This lets us put the
    * tty in non-blocking mode without affecting other processes that share it
    * with us.
    *
    * Example: `node | cat` - if we put our fd 0 in non-blocking mode, it also
    * affects fd 1 of `cat` because both file descriptors refer to the same
    * struct file in the kernel. When we reopen our fd 0, it points to a
    * different struct file, hence changing its properties doesn't affect
    * other processes.
    */
    if (type == UV_TTY) {
    r = uv__open_cloexec("/dev/tty", O_RDWR);

      /* Reopen the file descriptor when it refers to a tty. This lets us put the
       * tty in non-blocking mode without affecting other processes that share it
       * with us.
       *
       * Example: `node | cat` - if we put our fd 0 in non-blocking mode, it also
       * affects fd 1 of `cat` because both file descriptors refer to the same
       * struct file in the kernel. When we reopen our fd 0, it points to a
       * different struct file, hence changing its properties doesn't affect
       * other processes.
       */
      if (type == UV_TTY) {
        r = uv__open_cloexec("/dev/tty", O_RDWR);
    

    It appears that libuv assumes if the fd is a tty it must be the originating console.

    One workaround is to use an intermediate pipe:

    node -e 'process.stdout.write("wtf!\n")' | cat >/dev/ttys014
    
  3. ELLIOTTCABLE commented on Dec 10, 2015

    @ELLIOTTCABLE
    ContributorAuthor

    Hm. Okay, thanks for hunting that down for me; I might try to patch upstream.

    Either way, I'll leave this open until it's fixed there?

  4. kzc commented on Dec 10, 2015

    @kzc

    Yeah, I think it should be left open as it's a node regression.

    It does not happen on jxcore which is a pre 0.12 node fork. Haven't tried running on older versions of node 0.10 or node 0.12

    It was introduced here:

    libuv/libuv@b197515

  5. kzc commented on Dec 10, 2015

    @kzc
  6. ELLIOTTCABLE commented on Dec 10, 2015

    @ELLIOTTCABLE
    ContributorAuthor

    This looks like it may have been discussed before, by the way:

    libuv/libuv#528
    libuv/libuv#526

  7. added
    libuvIssues and PRs related to the libuv dependency or the uv binding.
    ttyIssues and PRs related to the tty subsystem.
    on Dec 10, 2015
  8. saghul commented on Dec 10, 2015

    @saghul
    Member

    Ahoi! @ELLIOTTCABLE can you try the patch in libuv/libuv#528? It should apply pretty much cleanly to deps/uv and the rebuild Node and test. Let me know if you run into issues with it.

  9. kzc commented on Dec 10, 2015

    @kzc

    The patch in libuv/libuv#528 appears to work on Mac against node v5.1.1 sources with stdout and stderr tty redirects. (Edit: patch as of Dec 10, 2015)

  10. kzc commented on Mar 23, 2016

    @kzc

    libuv patch status update: libuv/libuv#528 (comment)

  11. Gottox commented on Mar 23, 2016

    @Gottox

    Please have a look at libuv/libuv#779. I'm considering libuv/libuv#528 obsolete.

  12. kzc commented on Apr 7, 2016

    @kzc

    Fixed in libuv 1.9.0 upgrade #5994 c3cec1e

  13. mscdex commented on Apr 7, 2016

    @mscdex
    Contributor

    @ELLIOTTCABLE can you confirm this is fixed in master now with libuv 1.9.0?

  14. jasnell commented on Jun 6, 2016

    @jasnell
    Member

    Closing as this issue should be fixed.

  15. ELLIOTTCABLE commented on Jun 6, 2016

    @ELLIOTTCABLE
    ContributorAuthor

    Can confirm, functioning as expected in v6.2.1. 💯

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.libuvIssues and PRs related to the libuv dependency or the uv binding.ttyIssues and PRs related to the tty subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions