Skip to content

A libuv upgrade in Node v6 breaks the popular david package #6297

Description

@mgol
  • Version: v6.0.0-rc.3 (specifically, commit c3cec1e)
  • Platform: Darwin mgol-mbpro.local 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64
  • Subsystem: libuv

Unfortunately I don't have an isolated test case, I've only seen the david issue in all v6 RCs while it works fine in v5 & I reported it in alanshaw/david#106. I did a git bisect, though and nailed it down to c3cec1e.

Activity

  1. evanlucas commented on Apr 20, 2016

    @evanlucas
    Contributor
  2. added
    libuvIssues and PRs related to the libuv dependency or the uv binding.
    on Apr 20, 2016
  3. kzc commented on Apr 20, 2016

    @kzc

    v6.0.0-rc.2
    $ david

    @mgol It could be a tty issue in libuv 1.9.0.

    Can you try running:

    $ david | cat
    

    or

    $ david > out.txt
    $ cat out.txt
    
  4. mgol commented on Apr 20, 2016

    @mgol
    ContributorAuthor

    david | cat still prints truncated output while piping output to a file and cating the file works fine.

  5. kzc commented on Apr 20, 2016

    @kzc

    I can reproduce your original truncated david output problem with v6.0.0-pre. However, both commands in my previous comment above work for me on OSX 10.9.5.

  6. saghul commented on Apr 20, 2016

    @saghul
    Member

    I'll take a look. Main suspect: libuv/libuv@387102b

  7. mgol commented on Apr 20, 2016

    @mgol
    ContributorAuthor

    I'm on latest 10.11.4. I tried both in ZSH & Bash, same results every time.

  8. kzc commented on Apr 20, 2016

    @kzc

    If I apply this patch to master then david | cat fails (output truncated) here as well:

    diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c
    index 32fa37e..e2e5cb5 100644
    --- a/deps/uv/src/unix/tty.c
    +++ b/deps/uv/src/unix/tty.c
    @@ -80,7 +80,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
        * different struct file, hence changing its properties doesn't affect
        * other processes.
        */
    -  if (type == UV_TTY) {
    +  if (0 && type == UV_TTY) {
         /* Reopening a pty in master mode won't work either because the reopened
          * pty will be in slave mode (*BSD) or reopening will allocate a new
          * master/slave pair (Linux). Therefore check if the fd points to a
    
  9. kzc commented on Apr 20, 2016

    @kzc

    @saghul Might be an issue with uv_guess_handle not detecting a tty?

  10. kzc commented on Apr 20, 2016

    @kzc

    scratch that - uv_guess_handle correctly returns UV_TTY.

  11. kzc commented on Apr 20, 2016

    @kzc

    If this patch is applied to master with libuv 1.9.0 then david output is not truncated on OS X 10.9.5:

    diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c
    index 32fa37e..9179ca7 100644
    --- a/deps/uv/src/unix/tty.c
    +++ b/deps/uv/src/unix/tty.c
    @@ -135,8 +135,10 @@ skip:
       else
         flags |= UV_STREAM_WRITABLE;
    
    +#if 0
       if (!(flags & UV_STREAM_BLOCKING))
         uv__nonblock(fd, 1);
    +#endif
    
       uv__stream_open((uv_stream_t*) tty, fd, flags);
       tty->mode = UV_TTY_MODE_NORMAL;
  12. added a commit that references this issue on Apr 20, 2016
  13. kzc commented on Apr 20, 2016

    @kzc
  14. kzc commented on Apr 20, 2016

    @kzc

    I don't think the libuv tty PR is the issue. It appears that process.stdout is not being flushed upon process exit. Making stdout blocking as per patch above can make it work, but that's just side stepping the real issue.

    If the david script is changed to call process.exit() only upon encountering the process.stdout "drain" event then everything is output correctly with node master 0899ea7.

    What is considered to be the correct node way of flushing stdout upon process.exit()? I think this ought to happen automatically without programmer intervention.

  15. kzc commented on Apr 21, 2016

    @kzc

    Alternate fix - leave node 6.0.0-rc with libuv 1.9.0 as is and simply apply this patch to david:

    --- a/david/bin/david.js    2016-04-20 20:49:35.000000000 -0400
    +++ b/david/bin/david.js    2016-04-20 21:03:42.000000000 -0400
    @@ -325,7 +325,7 @@
           if (getNonWarnDepNames(deps).length ||
               getNonWarnDepNames(devDeps).length ||
               getNonWarnDepNames(optionalDeps).length) {
    -        process.exit(1)
    +        process.exitCode = 1
           } else {
             // Log feedback if all dependencies are up to date
             console.log(clc.green('All dependencies up to date'))
    

    This has the effect of letting the program exit naturally without abruptly cutting off the flushing of stdout.

  16. 50 remaining items

  17. Qix- commented on Apr 28, 2016

    @Qix-

    @kzc while that's a perfectly fine temporary solution, this is a simple problem within Node proper and should be fixed :P I don't think it's a consensus that process.exit() isn't changed; it needs to be changed.

  18. jasnell commented on Apr 28, 2016

    @jasnell
    Member

    @kzc ... I had a proposed PR that did exactly that but the consensus was that it's something that can be easily handled in userland. Essentially, if you want to exit gracefully while letting any stdio finish, you'll need to make sure that you're not adding anything to the event loop queue so that the process exits out on it's own naturally.

  19. kzc commented on Apr 28, 2016

    @kzc

    Exiting on its own naturally doesn't work in practise with complicated nested async logic without rewriting a lot of code.

    So if something like process.exitGracefully() is not added to node core all I can suggest is that everyone use the third party exit module and close this ticket.

  20. Qix- commented on Apr 28, 2016

    @Qix-

    @jasnell while I agree that's what users should be doing, the fact is that Node is being used as a scripting language and thus is more prone to users using pre-mature exit() calls.

    Since exit() itself (at least in modern times) flushes standard FDs we should emulate that in our async environment. It shouldn't need a special function call for it. Users that haven't pushed a lot of output and that don't normally see the bug described here should be completely unaffected.

  21. jasnell commented on Apr 28, 2016

    @jasnell
    Member

    @Qix- ... I agree with you :-) ... just need a PR that implements a solution that would be accepted.

  22. Qix- commented on Apr 28, 2016

    @Qix-

    @jasnell Haha okay :) 👍

  23. eljefedelrodeodeljefe commented on Apr 28, 2016

    @eljefedelrodeodeljefe
    Contributor

    @kzc I also see the need to handle this better and have it on my list, or would welcome a decent PR . node-exit's implementations is jut no proper solution. I am also hoping @Qix- would come up with something since your input above was valid.

    Can we close this issue or give it a proper name that reflects what the discussion was about though?

  24. kzc commented on Apr 28, 2016

    @kzc

    node-exit's implementations is jut no proper solution.

    @eljefedelrodeodeljefe What would you do differently than node-exit?

    https://github.com/cowboy/node-exit/blob/master/lib/exit.js

    Looks good to me, and it's known to work. Even supports closing streams other than stderr and stdout. Other than refactoring it to roll it into node proper, another solution would have to perform the same tasks.

  25. kzc commented on Apr 28, 2016

    @kzc

    @mgol Would you mind renaming this issue to something like "process.exit() ought to flush stdout/stderr"?

  26. jasnell commented on Apr 28, 2016

    @jasnell
    Member

    I'd be more inclined to close this particular issue as we have a couple others already in the tracker for this particular issue. The libuv update just brought the issue more to the forefront.

  27. kzc commented on Apr 28, 2016

    @kzc

    Well, david remains broken in node 6. So not sure why this issue should be closed. Discussion can certainly move to another Issue. Which one do you recommend @jasnell?

  28. eljefedelrodeodeljefe commented on Apr 28, 2016

    @eljefedelrodeodeljefe
    Contributor

    @kzc because their is no action item for libuv e.g. rolling back the change and no action item only for david. The solution will be something around a change of exit behavior, which is not per se broken.

    Concerning node-exit: this looks rather like a hack and you probably want to do this at the C or C++ layer, which was proposed already but didn't go forward. Also @jasnell had a solution, which which have added an API rather than fixing an existing one.

    reopen if you don't agree, but I think this can be closed in favor for #6456

  29. added
    docIssues and PRs related to Node.js documentation.
    and removed
    docIssues and PRs related to Node.js documentation.
    on Dec 1, 2016
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.libuvIssues and PRs related to the libuv dependency or the uv binding.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions