Skip to content

http: use autoDestroy: true in incoming message#33035

Closed
dnlup wants to merge 7 commits intonodejs:masterfrom
dnlup:_http_incoming_autodestroy
Closed

http: use autoDestroy: true in incoming message#33035
dnlup wants to merge 7 commits intonodejs:masterfrom
dnlup:_http_incoming_autodestroy

Conversation

@dnlup
Copy link
Contributor

@dnlup dnlup commented Apr 24, 2020

Enable the default autoDestroy: true option in IncomingMessage.

Refactor _http_client and _http_server to remove any manual destroying/closing of IncomingMessage.
Refactor IncomingMessage destroy method to use the standard implementation of the stream module and move the abort logic
inside of it.

Ref:

#30625

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines

@nodejs-github-bot nodejs-github-bot added the http Issues or PRs related to the http subsystem. label Apr 24, 2020
@dnlup dnlup force-pushed the _http_incoming_autodestroy branch from f4960e4 to 95d8354 Compare April 29, 2020 05:14
@ronag
Copy link
Member

ronag commented Apr 30, 2020

IncomingMessage overrides destroy() which kind of blocks any effort in this regards. That needs to IMO be fixed first.

@dnlup
Copy link
Contributor Author

dnlup commented May 1, 2020

IncomingMessage overrides destroy() which kind of blocks any effort in this regards. That needs to IMO be fixed first.

Thanks, @ronag, for the suggestion. I'll look into it. There is an issue with destroy for sure. When using keep-alive, we don't want to destroy the socket, and that's what's happening by just setting the option to true.

@dnlup dnlup force-pushed the _http_incoming_autodestroy branch from 95d8354 to 28da814 Compare May 4, 2020 08:28
@dnlup
Copy link
Contributor Author

dnlup commented May 6, 2020

Sorry if this is taking a long time, but I am trying to figure out what's wrong 🙏

Removing the override of destroy() resolves the EECONRESET errors, fewer tests are failing, but request is emitting close twice, and some connections seem to hang.

@dnlup dnlup force-pushed the _http_incoming_autodestroy branch 3 times, most recently from 336478c to 62e8aec Compare May 20, 2020 06:36
@dnlup dnlup marked this pull request as ready for review May 20, 2020 06:36
@dnlup dnlup force-pushed the _http_incoming_autodestroy branch from 62e8aec to 26a6e60 Compare May 20, 2020 07:09
@dnlup
Copy link
Contributor Author

dnlup commented May 20, 2020

The changes made here are overriding the ones you made recently, @ronag . I don't know if this approach is the best.

PS: just rebased against master on the last forced push.

@BridgeAR
Copy link
Member

@ronag PTAL

@BridgeAR BridgeAR requested a review from ronag May 27, 2020 23:56
Copy link
Member

@ronag ronag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also try to remove all cases of manually managing destroyed and emitting 'close' on IncomingMessage. Having some kind of hybrid solution will make things hard to maintain IMO.

@dnlup
Copy link
Contributor Author

dnlup commented May 28, 2020

Please also try to remove all cases of manually managing destroyed and emitting 'close' on IncomingMessage. Having some kind of hybrid solution will make things hard to maintain IMO.

You mean like in here? I agree, that is also the reason why the callback is not called in all cases in _destroy. I also agree that it is ugly, sorry. I wasn't sure I could change the _http_server.js parts.

Thanks for the pointers.

@BridgeAR BridgeAR force-pushed the master branch 2 times, most recently from 8ae28ff to 2935f72 Compare May 31, 2020 12:18
@dnlup
Copy link
Contributor Author

dnlup commented Jun 3, 2020

Do we need to keep this behavior? If we do, I think it would be better to implement the destroy logic directly in IncomingMessage and not reusing the general lib/internal/streams/destroy.js implementation as I did. Overriding that implementation causes a lot of tests to fail because they are expecting an unhandled error. Also, do you have anything against adding an abort method on IncomingMessage?

@ronag
Copy link
Member

ronag commented Jun 3, 2020

Do we need to keep this behavior?

Yes, just call destroy and move the logic there?

If we do, I think it would be better to implement the destroy logic directly in IncomingMessage and not reusing the general lib/internal/streams/destroy.js implementation as I did.

I disagree. We should implement it as a regular destroy.

Overriding that implementation causes a lot of tests to fail because they are expecting an unhandled error.

Can still be an unhandeld error?

Also, do you have anything against adding an abort method on IncomingMessage?

Yes, destroy should be abort. We just deprecated abort on ClientRequest in favor of destroy.

@dnlup
Copy link
Contributor Author

dnlup commented Jun 3, 2020

Yes, just call destroy and move the logic there?

Ok.

I disagree. We should implement it as a regular destroy.

I agree. The only difference I have seen with a regular destroy is that IncomingMessage emits an error only if there are listeners attached, at least when aborting.

Yes, destroy should be abort. We just deprecated abort on ClientRequest in favor of destroy.

Got it.

@ronag
Copy link
Member

ronag commented Jun 3, 2020

The only difference I have seen with a regular destroy is that IncomingMessage emits an error only if there are listeners attached, at least when aborting.

I can help with sorting this out. If you have any test that depends on this behavior just comment them out and we can take a look together when that's the only thing remaining.

@dnlup dnlup force-pushed the _http_incoming_autodestroy branch 4 times, most recently from 872f751 to 3231c42 Compare June 9, 2020 06:23
@kanongil
Copy link
Contributor

That test won't cover this case, since the response is immediately ended, and it does not read from the request.

For inspiration I made this code, which will incorrectly output REQ CLOSED on 15.5.0:

const Http = require('http');

const server = Http.createServer((req, res) => {

    console.log('REQ', req.method, req.url)

    req.on('data', (chunk) => {

        console.log('CHUNK', chunk.length)
    });

    req.on('close', () => console.log('REQ CLOSED'));
    res.on('close', () => console.log('RES CLOSED'));
});

server.listen(() => {

    const port = server.address().port;

    const req = Http.request({ port, method: 'GET' }, (res) => {

        console.log('GOT RES', res.statusCode);
        server.close();
    });

    req.end();
});

@dnlup
Copy link
Contributor Author

dnlup commented Dec 27, 2020

const Http = require('http');

const server = Http.createServer((req, res) => {

    console.log('REQ', req.method, req.url)

    req.on('data', (chunk) => {

        console.log('CHUNK', chunk.length)
    });

    req.on('close', () => console.log('REQ CLOSED'));
    res.on('close', () => console.log('RES CLOSED'));
});

server.listen(() => {

    const port = server.address().port;

    const req = Http.request({ port, method: 'GET' }, (res) => {

        console.log('GOT RES', res.statusCode);
        server.close();
    });

    req.end();
});

Thank you @kanongil , now I can see the difference.

@mcollina
Copy link
Member

We should revert this in v15 :/.

@dnlup
Copy link
Contributor Author

dnlup commented Dec 27, 2020

I apologize

@targos
Copy link
Member

targos commented Dec 27, 2020

Someone please open a revert PR against v15.x-staging

@ronag
Copy link
Member

ronag commented Dec 27, 2020

I apologize

Don’t worry. These things happen. Nobody’s fault. We’ll sort it out.

@ronag
Copy link
Member

ronag commented Dec 27, 2020

@dnlup do you want to try opening a revert PR against v15?

@ronag
Copy link
Member

ronag commented Dec 27, 2020

@nodejs/releasers we should probably add a note to the release notes for v16 regarding the change in behavior. Just ping me and I’ll be happy to author something.

@dnlup
Copy link
Contributor Author

dnlup commented Dec 27, 2020

@dnlup do you want to try opening a revert PR against v15?

@ronag Yes, I am going to try. I should revert all the 7 commits in master and open a PR to v15-staging branch, right?

eb14b10...8154e47

@dnlup
Copy link
Contributor Author

dnlup commented Dec 27, 2020

Sorry if it took me a while:

#36647

@devinivy devinivy mentioned this pull request Feb 2, 2021
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

http Issues or PRs related to the http subsystem. notable-change PRs with changes that should be highlighted in changelogs. semver-major PRs that contain breaking changes and should be released in the next major version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants