Skip to content

Possible bug in streams between node 8.1.4 and 8.2.0 #15029

Description

@SimenB
  • Version: 8.1.4 & 8.2.0
  • Platform: MacOS
  • Subsystem: Streams (or http?)

We have some code which uses pump, and between 8.1.4 and 8.2.0 the handler in certain cases stopped being called with an error. We have a test that our error handler is invoked correctly, which fails on newer versions of node.

In 8.1.4 we hit https://github.com/mafintosh/end-of-stream/blob/0ae1658b8167596fafbb9195363ada3bc5a3eaf2/index.js#L44, whilst in 8.2.0 (and later) we don't.

I've created a repository with reproduction code.

https://github.com/SimenB/node-stream-repro

Activity

  1. targos commented on Aug 25, 2017

    @targos
    Member

    @nodejs/streams

  2. SimenB commented on Aug 25, 2017

    @SimenB
    MemberAuthor

    Is this #14024?

  3. targos commented on Aug 25, 2017

    @targos
    Member

    That seems like a good candidate.

  4. SimenB commented on Aug 25, 2017

    @SimenB
    MemberAuthor

    Our code for this particular case is really hairy, so if it was an actual bug, and the fix is backported to 6, I'll with great joy remove our current handling of it 🙂

  5. mcollina commented on Aug 25, 2017

    @mcollina
    SponsorMember

    Can you please verify with 8.4.0?

  6. SimenB commented on Aug 25, 2017

    @SimenB
    MemberAuthor

    8.2.0, 8.2.1, 8.3.0 and 8.4.0 all behave the same

  7. SimenB commented on Aug 25, 2017

    @SimenB
    MemberAuthor

    6.11.2, 7.11.1, 8.0.0, 8.1.0 and 8.1.4 also behave the same, FWIW. So something changed between 8.1.4 and 8.2.0

  8. trygve-lie commented on Aug 25, 2017

    @trygve-lie

    So fare I see: Under the hood, pump uses end-of-stream. In version 8.1.4 and older end-of-stream get a close event from the underlaying stream (which then are used to throw an Error further up). In version 8.2.0 and newer end-of-stream get a finish event from the underlaying stream.

  9. mcollina commented on Aug 25, 2017

    @mcollina
    SponsorMember

    I think the bug is more subtle than this. I would like not to revert #14024, and figure out what events changed.

    Can you reproduce the bug without Express and got?

  10. SimenB commented on Aug 25, 2017

    @SimenB
    MemberAuthor

    I've pushed usage of request instead of fetch. Never used got (it's get from http). Can look into removing express on Monday

  11. mcollina commented on Aug 25, 2017

    @mcollina
    SponsorMember

    I meant, can you just show this using node core?

  12. added
    streamIssues and PRs related to Node.js streams.
    on Aug 25, 2017
  13. SimenB commented on Aug 29, 2017

    @SimenB
    MemberAuthor

    @mcollina I've reduced the example down to just http and pump

  14. trygve-lie commented on Aug 29, 2017

    @trygve-lie

    Here is a stipped down version:

    const { get, createServer } = require('http');
    
    let external;
    
    // Http server
    createServer((req, res) => {
        res.writeHead(200);
        setTimeout(() => {
            external.abort();
            res.end('Hello World\n');
        }, 1000);
    }).listen(3000);
    
    // Proxy server
    createServer((req, res) => {
        get('http://127.0.0.1:3000', inner => {
            res.on('close', () => {
                console.log('response writable:', res.writable);
            });
            inner.pipe(res);
        });
    }).listen(3001, () => {
        external = get('http://127.0.0.1:3001');
    });

    What happens here is that we (external) do a request to a server (proxy server) which stream data through from a second server (http serve) and we terminate the request before the stream is done. A real use case for this is ex a user hitting the stop button in the browser while the server is still piping data to it.

    If one run the above in node 8.1.4 or older, response writable: true will be printed. If one run the above in node 8.2.0 or newer, response writable: false will be printed.

    In other words; in node 8.1.4 and older it seems like the writable response stream was writable after a close event. This would again create a problem where the stream could be written too after it was closed.

    To me this looks like a fixed bug in node 8.2.0 and not a new bug. What make it looks like a bug is that libraries such as end-of-stream and pump suddenly stopped providing error objects on the above scenario between two versions of node.

    If anyone can confirm that the above behaviour is correct (the response should not be writable after a close event), I'll be happy to report this to end-of-stream and pump so they can account for this change between the node versions.

  15. 4 remaining items

  16. trygve-lie commented on Aug 30, 2017

    @trygve-lie

    The stream are terminated prematurelly in all versions. In node 8.1.4 and older eos (pump have this "error" inheritated from eos) ends with an error object telling us that. In 8.2.0 eos ends with no error so in newer versions we really do not know that the stream was terminated prematurelly.

    I am not sure how eos will be able to figure this out now. I created an issue on it: mafintosh/end-of-stream#14

  17. mcollina commented on Aug 30, 2017

    @mcollina
    SponsorMember

    @trygve-lie I understand the problem now. pump is calling .end()  on the response, causing res.writable to go to false. This prevents eos  to call the callback with the error.

    I think it's a bug in core. stream.Writable sets ws.writable = false after emitting 'finish' , while OutgoingMessage sets ws.writable = true before emitting 'finish'.

  18. mcollina commented on Sep 13, 2017

    @mcollina
    SponsorMember

    I was absolutely wrong in what I said. What's happening is clear to me, but not how to fix this and maintain #14024. I'll be reverting that asap.

  19. jasnell commented on Sep 13, 2017

    @jasnell
    Member

    Reverting #14024 and revisiting it later looks like the only viable path forward on this.

  20. SimenB commented on Sep 14, 2017

    @SimenB
    MemberAuthor

    What's happening is clear to me

    I'm curios, could you expand on that?

    EDIT: Done in #15404 (comment), so no need to do so here. Thanks!

  21. added a commit that references this issue on Sep 20, 2017
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

    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