Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: introduce custom smart pointers for BaseObjects #30374

Closed
wants to merge 5 commits into from

Conversation

addaleax
Copy link
Member

Note: Some of the commits here are from https://github.com/nodejs/quic/, where this concept has proven useful so far.

src: introduce custom smart pointers for BaseObjects

Referring to BaseObject instances using standard C++ smart pointers
can interfere with BaseObject’s own cleanup mechanisms
(explicit delete, delete-on-GC and delete-on-cleanup).

Introducing custom smart pointers allows referring to BaseObjects
safely while keeping those mechanisms intact.

Refs: nodejs/quic#141
Refs: nodejs/quic#149
Reviewed-By: James M Snell jasnell@gmail.com

http2: use custom BaseObject smart pointers

Refs: nodejs/quic#141
Reviewed-By: James M Snell jasnell@gmail.com

src: use BaseObjectPtr for keeping channel alive in dns bindings
src: remove keep alive option from SetImmediate()

This is no longer necessary now that the copyable BaseObjectPtr
is available (as opposed to the only-movable v8::Global).

src: remove HandleWrap instances from list once closed

This allows keeping BaseObjectPtrs to HandleWrap instances.
Previously, the pointer kept the HandleWrap object alive, leaving
the Environment cleanup code that waits for the handle list to drain
in a busy loop, because only the HandleWrap destructor removed
the item from the list.

Refs: nodejs/quic#165
Reviewed-By: James M Snell jasnell@gmail.com
Reviewed-By: Daniel Bevenius daniel.bevenius@gmail.com

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines

Referring to `BaseObject` instances using standard C++ smart pointers
can interfere with BaseObject’s own cleanup mechanisms
(explicit delete, delete-on-GC and delete-on-cleanup).

Introducing custom smart pointers allows referring to `BaseObject`s
safely while keeping those mechanisms intact.

Refs: nodejs/quic#141
Refs: nodejs/quic#149
Reviewed-By: James M Snell <jasnell@gmail.com>
Refs: nodejs/quic#141
Reviewed-By: James M Snell <jasnell@gmail.com>
This is no longer necessary now that the copyable `BaseObjectPtr`
is available (as opposed to the only-movable `v8::Global`).
This allows keeping `BaseObjectPtr`s to `HandleWrap` instances.
Previously, the pointer kept the `HandleWrap` object alive, leaving
the Environment cleanup code that waits for the handle list to drain
in a busy loop, because only the `HandleWrap` destructor removed
the item from the list.

Refs: nodejs/quic#165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. labels Nov 12, 2019
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@addaleax addaleax added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Nov 12, 2019
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

addaleax added a commit that referenced this pull request Nov 19, 2019
Referring to `BaseObject` instances using standard C++ smart pointers
can interfere with BaseObject’s own cleanup mechanisms
(explicit delete, delete-on-GC and delete-on-cleanup).

Introducing custom smart pointers allows referring to `BaseObject`s
safely while keeping those mechanisms intact.

Refs: nodejs/quic#141
Refs: nodejs/quic#149
Reviewed-By: James M Snell <jasnell@gmail.com>

PR-URL: #30374
Refs: nodejs/quic#165
Reviewed-By: David Carlier <devnexen@gmail.com>
addaleax added a commit that referenced this pull request Nov 19, 2019
Refs: nodejs/quic#141
Reviewed-By: James M Snell <jasnell@gmail.com>

PR-URL: #30374
Refs: nodejs/quic#149
Refs: nodejs/quic#165
Reviewed-By: David Carlier <devnexen@gmail.com>
addaleax added a commit that referenced this pull request Nov 19, 2019
PR-URL: #30374
Refs: nodejs/quic#141
Refs: nodejs/quic#149
Refs: nodejs/quic#141
Refs: nodejs/quic#165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
addaleax added a commit that referenced this pull request Nov 19, 2019
This is no longer necessary now that the copyable `BaseObjectPtr`
is available (as opposed to the only-movable `v8::Global`).

PR-URL: #30374
Refs: nodejs/quic#141
Refs: nodejs/quic#149
Refs: nodejs/quic#141
Refs: nodejs/quic#165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
addaleax added a commit that referenced this pull request Nov 19, 2019
This allows keeping `BaseObjectPtr`s to `HandleWrap` instances.
Previously, the pointer kept the `HandleWrap` object alive, leaving
the Environment cleanup code that waits for the handle list to drain
in a busy loop, because only the `HandleWrap` destructor removed
the item from the list.

Refs: nodejs/quic#165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>

PR-URL: #30374
Refs: nodejs/quic#141
Refs: nodejs/quic#149
Refs: nodejs/quic#141
Reviewed-By: David Carlier <devnexen@gmail.com>
@addaleax
Copy link
Member Author

Landed in efce655...1317ac6

@addaleax addaleax closed this Nov 19, 2019
@addaleax addaleax deleted the baseobjectptr branch November 19, 2019 13:00
@BridgeAR
Copy link
Member

@addaleax should this be backported or is this blocked on another PR that should be backported first? It does not land cleanly on our v13.x-staging currently. Please either update the labels accordingly or open a manual backport, thanks!

@addaleax
Copy link
Member Author

I think this should have an easier time landing after the V8 7.9 backport.

MylesBorins pushed a commit that referenced this pull request Nov 21, 2019
Referring to `BaseObject` instances using standard C++ smart pointers
can interfere with BaseObject’s own cleanup mechanisms
(explicit delete, delete-on-GC and delete-on-cleanup).

Introducing custom smart pointers allows referring to `BaseObject`s
safely while keeping those mechanisms intact.

Refs: nodejs/quic#141
Refs: nodejs/quic#149
Reviewed-By: James M Snell <jasnell@gmail.com>

PR-URL: #30374
Refs: nodejs/quic#165
Reviewed-By: David Carlier <devnexen@gmail.com>
MylesBorins pushed a commit to addaleax/node that referenced this pull request Apr 1, 2020
PR-URL: nodejs#30374
Refs: nodejs/quic#141
Refs: nodejs/quic#149
Refs: nodejs/quic#141
Refs: nodejs/quic#165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
MylesBorins pushed a commit to addaleax/node that referenced this pull request Apr 1, 2020
This is no longer necessary now that the copyable `BaseObjectPtr`
is available (as opposed to the only-movable `v8::Global`).

PR-URL: nodejs#30374
Refs: nodejs/quic#141
Refs: nodejs/quic#149
Refs: nodejs/quic#141
Refs: nodejs/quic#165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
MylesBorins pushed a commit to addaleax/node that referenced this pull request Apr 1, 2020
This allows keeping `BaseObjectPtr`s to `HandleWrap` instances.
Previously, the pointer kept the `HandleWrap` object alive, leaving
the Environment cleanup code that waits for the handle list to drain
in a busy loop, because only the `HandleWrap` destructor removed
the item from the list.

Refs: nodejs/quic#165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>

PR-URL: nodejs#30374
Refs: nodejs/quic#141
Refs: nodejs/quic#149
Refs: nodejs/quic#141
Reviewed-By: David Carlier <devnexen@gmail.com>
MylesBorins pushed a commit to addaleax/node that referenced this pull request Apr 1, 2020
This was overlooked in a489583.

Refs: nodejs#30374

PR-URL: nodejs#30666
Fixes: nodejs#30643
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit to addaleax/node that referenced this pull request Apr 1, 2020
This is in preparation for running native `SetImmediate()`
callbacks during shutdown.

PR-URL: nodejs#30666
Fixes: nodejs#30643
Refs: nodejs#30374
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit to addaleax/node that referenced this pull request Apr 1, 2020
Guard against running `SetImmediate()` from the destructor.
The object will not be alive or usable in the callback,
so it does not make sense to attempt to schedule the
`SetImmediate()`.

PR-URL: nodejs#30666
Fixes: nodejs#30643
Refs: nodejs#30374
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit to addaleax/node that referenced this pull request Apr 1, 2020
This can be necessary, because some parts of the Node.js code base
perform cleanup operations in the Immediate callbacks, e.g. HTTP/2.

This resolves flakiness in an HTTP/2 test that failed when a
`SetImmediate()` callback was not run or destroyed before the
`Environment` destructor started, because that callback held a
strong reference to the `Http2Session` object and the expectation
was that no such objects exist once the `Environment` constructor
starts.

Another, slightly more direct, alternative would have
been to clear the immediate queue rather than to run it. However,
this approach seems to make more sense as code generally assumes
that the `SetImmediate()` callback will always run; For example,
N-API uses an immediate callback to call buffer finalization
callbacks.

Unref’ed immediates are skipped, as the expectation is generally
that they may not run anyway.

Fixes: nodejs#30643

PR-URL: nodejs#30666
Refs: nodejs#30374
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit to addaleax/node that referenced this pull request Apr 1, 2020
Fix the condition for deleting the underlying data pointed to by
a `BaseObjectWeakPtr`, which erroneously skipped that deletion
when `ptr->get()` was `nullptr`. This fixes a memory leak reported
by some of the tests.

Refs: nodejs#30374 (comment)

PR-URL: nodejs#32393
Reviewed-By: Matheus Marchini <mat@mmarchini.me>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 1, 2020
Referring to `BaseObject` instances using standard C++ smart pointers
can interfere with BaseObject’s own cleanup mechanisms
(explicit delete, delete-on-GC and delete-on-cleanup).

Introducing custom smart pointers allows referring to `BaseObject`s
safely while keeping those mechanisms intact.

Refs: nodejs/quic#141
Refs: nodejs/quic#149
Reviewed-By: James M Snell <jasnell@gmail.com>

Backport-PR-URL: #32301
PR-URL: #30374
Refs: nodejs/quic#165
Reviewed-By: David Carlier <devnexen@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 1, 2020
Refs: nodejs/quic#141
Reviewed-By: James M Snell <jasnell@gmail.com>

Backport-PR-URL: #32301
PR-URL: #30374
Refs: nodejs/quic#149
Refs: nodejs/quic#165
Reviewed-By: David Carlier <devnexen@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 1, 2020
Backport-PR-URL: #32301
PR-URL: #30374
Refs: nodejs/quic#141
Refs: nodejs/quic#149
Refs: nodejs/quic#141
Refs: nodejs/quic#165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 1, 2020
This is no longer necessary now that the copyable `BaseObjectPtr`
is available (as opposed to the only-movable `v8::Global`).

Backport-PR-URL: #32301
PR-URL: #30374
Refs: nodejs/quic#141
Refs: nodejs/quic#149
Refs: nodejs/quic#141
Refs: nodejs/quic#165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 1, 2020
This allows keeping `BaseObjectPtr`s to `HandleWrap` instances.
Previously, the pointer kept the `HandleWrap` object alive, leaving
the Environment cleanup code that waits for the handle list to drain
in a busy loop, because only the `HandleWrap` destructor removed
the item from the list.

Refs: nodejs/quic#165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>

Backport-PR-URL: #32301
PR-URL: #30374
Refs: nodejs/quic#141
Refs: nodejs/quic#149
Refs: nodejs/quic#141
Reviewed-By: David Carlier <devnexen@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 1, 2020
This was overlooked in a489583.

Refs: #30374

Backport-PR-URL: #32301
PR-URL: #30666
Fixes: #30643
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 1, 2020
This is in preparation for running native `SetImmediate()`
callbacks during shutdown.

Backport-PR-URL: #32301
PR-URL: #30666
Fixes: #30643
Refs: #30374
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 1, 2020
Guard against running `SetImmediate()` from the destructor.
The object will not be alive or usable in the callback,
so it does not make sense to attempt to schedule the
`SetImmediate()`.

Backport-PR-URL: #32301
PR-URL: #30666
Fixes: #30643
Refs: #30374
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 1, 2020
This can be necessary, because some parts of the Node.js code base
perform cleanup operations in the Immediate callbacks, e.g. HTTP/2.

This resolves flakiness in an HTTP/2 test that failed when a
`SetImmediate()` callback was not run or destroyed before the
`Environment` destructor started, because that callback held a
strong reference to the `Http2Session` object and the expectation
was that no such objects exist once the `Environment` constructor
starts.

Another, slightly more direct, alternative would have
been to clear the immediate queue rather than to run it. However,
this approach seems to make more sense as code generally assumes
that the `SetImmediate()` callback will always run; For example,
N-API uses an immediate callback to call buffer finalization
callbacks.

Unref’ed immediates are skipped, as the expectation is generally
that they may not run anyway.

Fixes: #30643

Backport-PR-URL: #32301
PR-URL: #30666
Refs: #30374
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 1, 2020
Fix the condition for deleting the underlying data pointed to by
a `BaseObjectWeakPtr`, which erroneously skipped that deletion
when `ptr->get()` was `nullptr`. This fixes a memory leak reported
by some of the tests.

Refs: #30374 (comment)

Backport-PR-URL: #32301
PR-URL: #32393
Reviewed-By: Matheus Marchini <mat@mmarchini.me>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
@codebytere codebytere mentioned this pull request Apr 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants