Skip to content

fix: microtasks policy in CreateEnvironment#29531

Merged
zcbenz merged 7 commits into
electron:mainfrom
indutny:fix/gh-29463
Jun 21, 2021
Merged

fix: microtasks policy in CreateEnvironment#29531
zcbenz merged 7 commits into
electron:mainfrom
indutny:fix/gh-29463

Conversation

@indutny

@indutny indutny commented Jun 3, 2021

Copy link
Copy Markdown
Contributor

Description of Change

Microtasks policy should not be updated for the renderer because
NodeBindings::CreateEnvironment might be entered with or without
UvRunOnce() on stack. One of the examples of such calls is
window.open() which is possible to invoke while uv_run() is still
running (e.g. with setImmediate()).

All in all, it doesn't matter that much which policy we use since
v8::MicrotasksScope has a check for the policy in its destructor and
no commits will be made if the policy is kExplicit. It is important,
however, to not change the policy in the middle of UvRunOnce() so we
should respect whatever we currently have and move on.

Fix: #29463

cc @nornagon @codebytere @deepak1556

Checklist

Release Notes

Notes: fix crashes in debug builds caused by microtasks policy mismatch

Microtasks policy should not be updated for the renderer because
`NodeBindings::CreateEnvironment` might be entered with or without
`UvRunOnce()` on stack. One of the examples of such calls is
`window.open()` which is possible to invoke while `uv_run()` is still
running (e.g. with `setImmediate()`).

All in all, it doesn't matter that much which policy we use since
`v8::MicrotasksScope` has a check for the policy in its destructor and
no commits will be made if the policy is `kExplicit`. It is important,
however, to not change the policy in the middle of `UvRunOnce()` so we
should respect whatever we currently have and move on.

Fix: electron#29463
@indutny

indutny commented Jun 3, 2021

Copy link
Copy Markdown
Contributor Author

@nornagon I've used your test, but didn't ask for permission. Please let me know if this is not okay with you, and I'll write something else in its place.

@indutny

indutny commented Jun 3, 2021

Copy link
Copy Markdown
Contributor Author

I should have probably used crash-cases for the test. Let me follow-up on this real quick.

@indutny-signal

Copy link
Copy Markdown
Contributor

Done.

@nornagon

nornagon commented Jun 3, 2021

Copy link
Copy Markdown
Contributor

@indutny no problem from me, thanks for asking.

Comment thread spec-main/fixtures/crash-cases/setimmediate-window-open-crash/index.html Outdated
Comment thread spec-main/fixtures/crash-cases/setimmediate-window-open-crash/index.html Outdated
Comment on lines 479 to +481
// Match Blink's behavior by allowing microtasks invocation to be controlled
// by MicrotasksScope objects.
is.policy = v8::MicrotasksPolicy::kScoped;
is.policy = context->GetIsolate()->GetMicrotasksPolicy();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This comment is now incorrect, right? Is the new behavior safe? Why was this the way it was before?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It was introduced in 103fea5 originally by @zcbenz . @zcbenz could you take a look at this PR?

I believe it is safe to do it the way because everything outside of UvRunOnce() would have scoped policy, and all C++ code invokes from UvRunOnce() will have kExplicit. This PR doesn't change this behavior at all, but just makes sure that we don't change back to kScoped while we are in UvRunOnce().

As stated in the PR description, using kExplicit with MicrotasksScope is safe because of this check in v8.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changed the comment to reflect new behavior.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It was introduced in 103fea5 originally by @zcbenz . @zcbenz could you take a look at this PR?

I don't quite remember the background of the change, but we have a test for the original issue so as long as the tests are passing there should be no problem.

@indutny indutny requested a review from nornagon June 4, 2021 06:06
@codebytere codebytere added target/12-x-y semver/patch backwards-compatible bug fixes labels Jun 4, 2021
@electron-cation electron-cation Bot removed the new-pr 🌱 PR opened recently label Jun 4, 2021
@indutny

indutny commented Jun 9, 2021

Copy link
Copy Markdown
Contributor Author

@nornagon kindly reminding about it. Thanks!

@nornagon nornagon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM with updated comment.

// by MicrotasksScope objects when queued outside of `UvRunOnce()` call, but
// use explicit microtasks policy while inside `UvRunOnce()` for better
// compatibility with Node.js and better performance.
is.policy = context->GetIsolate()->GetMicrotasksPolicy();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the comment here could be a little clearer, let's go with something like:

Blink expects the microtasks policy to be kScoped, but Node.js expects it to be kExplicit. In the renderer, there can be many contexts within the same isolate, so we don't want to change the existing policy here, which could be either kExplicit or kScoped depending on whether we're executing from within a Node.js or a Blink entrypoint. Instead, the policy is toggled to kExplicit when entering Node.js through UvRunOnce.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ack. Thanks for writing a much better comment than I was capable of 😅

@zcbenz zcbenz merged commit d4a1b41 into electron:main Jun 21, 2021
@release-clerk

release-clerk Bot commented Jun 21, 2021

Copy link
Copy Markdown

Release Notes Persisted

fix crashes in debug builds caused by microtasks policy mismatch

@trop

trop Bot commented Jun 21, 2021

Copy link
Copy Markdown
Contributor

I have automatically backported this PR to "12-x-y", please check out #29807

@trop trop Bot removed the target/12-x-y label Jun 21, 2021
@trop

trop Bot commented Jun 21, 2021

Copy link
Copy Markdown
Contributor

I have automatically backported this PR to "13-x-y", please check out #29808

@trop

trop Bot commented Jun 21, 2021

Copy link
Copy Markdown
Contributor

I have automatically backported this PR to "14-x-y", please check out #29809

BlackHole1 pushed a commit to BlackHole1/electron that referenced this pull request Aug 30, 2021
* fix: microtasks policy in CreateEnvironment

Microtasks policy should not be updated for the renderer because
`NodeBindings::CreateEnvironment` might be entered with or without
`UvRunOnce()` on stack. One of the examples of such calls is
`window.open()` which is possible to invoke while `uv_run()` is still
running (e.g. with `setImmediate()`).

All in all, it doesn't matter that much which policy we use since
`v8::MicrotasksScope` has a check for the policy in its destructor and
no commits will be made if the policy is `kExplicit`. It is important,
however, to not change the policy in the middle of `UvRunOnce()` so we
should respect whatever we currently have and move on.

Fix: electron#29463

* Move test to a better place

* Update spec-main/fixtures/crash-cases/setimmediate-window-open-crash/index.html

Co-authored-by: Jeremy Rose <[email protected]>

* Update spec-main/fixtures/crash-cases/setimmediate-window-open-crash/index.html

Co-authored-by: Jeremy Rose <[email protected]>

* simplify crash-case

* comment

* fix comment

Co-authored-by: Fedor Indutny <[email protected]>
Co-authored-by: Jeremy Rose <[email protected]>
Co-authored-by: Fedor Indutny <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver/patch backwards-compatible bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Microtasks policy incorrect, leading to DCHECK, when calling window.open from setImmediate

6 participants