FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

http: defer reentrant execution of Parser::Execute by ShogunPanda · Pull Request #43369 · nodejs/node · GitHub

/ node Public

http: defer reentrant execution of Parser::Execute - #43369

Closed
ShogunPanda wants to merge 6 commits into
nodejs:mainfrom
ShogunPanda:http-defer-execute
Closed

http: defer reentrant execution of Parser::Execute#43369
ShogunPanda wants to merge 6 commits into
nodejs:mainfrom
ShogunPanda:http-defer-execute

Conversation

Copy link
Copy Markdown
Contributor

This PR fixes an edge case in which Parser::Execute is called within the callback of one of its events.

Fixes: #39671

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/http
  • @nodejs/net

nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. http_parser Issues and PRs related to the HTTP Parser dependency or the http_parser binding. needs-ci PRs that need a full CI run. labels Jun 10, 2022
Comment thread src/node_http_parser.cc Outdated
Comment thread src/node_http_parser.cc Outdated
Comment thread src/node_http_parser.cc Outdated

Copy link
Copy Markdown
Member

Good work!

Copy link
Copy Markdown
Member

The problematic parser->current_buffer_.IsEmpty() check is a speed hack; it's explicitly documented as such. Adding a hack to work around a hack is not a good idea.

My suggestion: remove current_buffer_. That simplifies the parser and makes it re-entrant again. Worry about performance afterwards.

I speculate the hit won't be so bad, and can probably be fixed by doing the bookkeeping in JS land.

ShogunPanda commented Jun 13, 2022
edited
Loading

Copy link
Copy Markdown
Contributor Author

@bnoordhuis Are you suggesting to remove that just in Execute, isn't it?

Copy link
Copy Markdown
Member

current_buffer_ is used to thread through the buffer from a parser.execute(buffer) call from JS through C++ to the JS callback parser[kOnBody] = parserOnBody(buffer, start, len) { /* ... */ }.

That threading through isn't necessary. Just set parser.buffer = buffer before calling parser.execute(buffer) and the callback can access it as this.buffer.

Node can short-circuit and pass data directly from libuv to the callback without going through parser.execute(buffer) first but the callback can detect that by doing buffer = this.buffer ?? buffer.

OnStreamRead()should be modified to create a new buffer instead of reusing current_buffer_. In theory that's a performance hit but I expect it's a wash because the callback no longer needs to call buffer.slice().


If I had infinite free time, I'd rewrite the parser to get rid of C++ -> JS callbacks and just return parse info. It'd get rid of so much complexity and inefficiency.

Copy link
Copy Markdown
Contributor Author

Actually I was able to remove the current_buffer_ at all and apparently nothing changes.
The only relevant change is in on_body where I always do:

Local<Object> current_buffer_ = scope.Escape(Buffer::Copy(
        env()->isolate(),
        current_buffer_data_,
        current_buffer_len_).ToLocalChecked());

Do you see any problem in this?

Copy link
Copy Markdown
Contributor Author

@addaleax @bnoordhuis I've sent my latest version which removes current_buffer_ and thus also removes needs for all the suggestion Anna asked about. Can you please take a look again?

Comment thread src/node_http_parser.cc Outdated
ShogunPanda force-pushed the http-defer-execute branch 2 times, most recently from 97fbe67 to 5c2884b Compare June 15, 2022 08:41

Copy link
Copy Markdown
Contributor Author

@bnoordhuis I applied your changes (plus few additional required changes). How does it look now?

Copy link
Copy Markdown
Member

Is there a reason you didn't update lib/_http_common.js? You don't need to slice anymore, or pass the start and len arguments.

Copy link
Copy Markdown
Contributor Author

@bnoordhuis The answer is obvious: I forgot. X°°°D Done now!

Comment thread src/node_http_parser.cc Outdated
Comment thread src/node_http_parser.cc Outdated

bnoordhuis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Nice, good work!

@addaleax I'll go ahead and dismiss your review. Looks like all actionable feedback's been addressed.

ShogunPanda commented Jun 17, 2022
edited
Loading

Copy link
Copy Markdown
Contributor Author

@bnoordhuis The last item would be to try to test it without using the parser directly. I'll give it a try today but this can go out without as well.

Done!

mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

lgtm

wow, when a PR fixes a bug and reduces code, it's doing something right.

Copy link
Copy Markdown
Contributor Author

Thanks sir :)

Copy link
Copy Markdown
Collaborator

Copy link
Copy Markdown
Contributor Author

@nodejs/http Can anybody reapprove this so I can land it?

mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

lgtm

Copy link
Copy Markdown
Contributor Author

Landed in b970634

ShogunPanda added a commit that referenced this pull request Jun 22, 2022
PR-URL: #43369
Fixes: #39671
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>

j-catania commented Jun 27, 2022
edited
Loading

Copy link
Copy Markdown

Hello @ShogunPanda

Thanks for your work !
Can you please tell me in which version of NodeJS is it fixed please ?

Copy link
Copy Markdown
Contributor Author

@j-catania It was merged in main, which means it will be available in the next 18 release, I think 18.5.0. Not sure it will be backported.

ShogunPanda deleted the http-defer-execute branch June 27, 2022 07:26

Copy link
Copy Markdown
Contributor

Is there a way to help see this backported to 16.x? This bug is really biting us as we are doing file uploads, and the 18 LTS release is still ~4 months off so upgrading isn't an option for us, and that we expect surrounding infra will take a few months to add 18 support after it releases.

Copy link
Copy Markdown
Contributor Author

Is there a way to help see this backported to 16.x? This bug is really biting us as we are doing file uploads, and the 18 LTS release is still ~4 months off so upgrading isn't an option for us, and that we expect surrounding infra will take a few months to add 18 support after it releases.

@nodejs/tsc Can we do this? What is the policy about backporting?

aduh95 commented Jun 28, 2022

Copy link
Copy Markdown
Contributor

## What can be backported?
The "Current" release line is much more lenient than the LTS release lines in
what can be landed. Our LTS release lines (see the [Release Plan][])
require that commits mature in the Current release for at least 2 weeks before
they can be landed in an LTS staging branch. Only after "maturation" will those
commits be cherry-picked or backported.

Copy link
Copy Markdown
Member

Is there a way to help see this backported to 16.x? This bug is really biting us as we are doing file uploads, and the 18 LTS release is still ~4 months off so upgrading isn't an option for us, and that we expect surrounding infra will take a few months to add 18 support after it releases.

@nodejs/tsc Can we do this? What is the policy about backporting?

Standard policy is:

  • Semver patch commits can be backported to LTS although we prefer to have them go have been in a current release for at least two weeks first (https://github.com/nodejs/Release#lts-staging-branches).
  • Semver minor changes, in addition to the "two weeks in current" guideline, would wait for the next semver minor LTS release (generally one per quarter).

ShogunPanda commented Jun 28, 2022
edited
Loading

Copy link
Copy Markdown
Contributor Author

Thanks both.
In other words, in this particular case, I think the change is semver-patch. So I will be able to send a backport PR in about two weeks from the release of 18.5.0. Am I right?

aduh95 commented Jun 28, 2022
edited
Loading

Copy link
Copy Markdown
Contributor

If the commit lands cleanly on v16.x-staging, there's no need for a backport PR:

## What needs to be backported?
If a cherry-pick from `main` does not land cleanly on a staging branch, the
releaser will mark the pull request with a particular label for that release
line (e.g. `backport-requested-vN.x`), specifying to our tooling that this
pull request should not be included. The releaser will then add a comment
requesting that a backport pull request be made.

If a backport PR is necessary, you don't need to wait two weeks for opening it, but the LTS team won't land it until it's been on a Current version for at least two weeks.

Copy link
Copy Markdown
Contributor Author

I see.
Given that you added the label now, the tooling will try to perform the landing automatically, isn't it?

aduh95 commented Jun 28, 2022

Copy link
Copy Markdown
Contributor

No, someone from @nodejs/lts will (try to) do it when preparing the next release, or leave a comment here if there's a conflict.

targos pushed a commit that referenced this pull request Jul 12, 2022
PR-URL: #43369
Fixes: #39671
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
targos pushed a commit that referenced this pull request Jul 31, 2022
PR-URL: #43369
Fixes: #39671
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
guangwong pushed a commit to noslate-project/node that referenced this pull request Oct 10, 2022
PR-URL: nodejs/node#43369
Fixes: nodejs/node#39671
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. http_parser Issues and PRs related to the HTTP Parser dependency or the http_parser binding.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Assertion `parser->current_buffer_.IsEmpty()' failed

Back | FazBrowse Home | New Git URL