diff options
author | Anna Henningsen <anna@addaleax.net> | 2020-10-03 23:45:08 +0300 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2020-10-07 11:54:34 +0300 |
commit | 40364b181d44ba90b6ce7cda4f9e3297581121c5 (patch) | |
tree | 274285afac266cdd10973c40cdfdaf1c79f36fdf /src/node_worker.cc | |
parent | bc0c094b74063b81a831396988ffed291cc80e77 (diff) |
src: add check against non-weak BaseObjects at process exit
When a process exits cleanly, i.e. because the event loop ends up
without things to wait for, the Node.js objects that are left on
the heap should be:
1. weak, i.e. ready for garbage collection once no longer
referenced, or
2. detached, i.e. scheduled for destruction once no longer
referenced, or
3. an unrefed libuv handle, i.e. does not keep the event loop
alive, or
4. an inactive libuv handle (essentially the same here)
There are a few exceptions to this rule, but generally,
if there are C++-backed Node.js objects on the heap
that do not fall into the above categories, we may be looking
at a potential memory leak. Most likely, the cause is a missing
`MakeWeak()` call on the corresponding object.
In order to avoid this kind of problem, we check the list
of BaseObjects for these criteria. In this commit, we only do so
when explicitly instructed to or when in debug mode
(where --verify-base-objects is always-on).
In particular, this avoids the kinds of memory leak issues
that were fixed in the PRs referenced below.
Refs: https://github.com/nodejs/node/pull/35488
Refs: https://github.com/nodejs/node/pull/35487
Refs: https://github.com/nodejs/node/pull/35481
PR-URL: https://github.com/nodejs/node/pull/35490
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Diffstat (limited to 'src/node_worker.cc')
-rw-r--r-- | src/node_worker.cc | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/src/node_worker.cc b/src/node_worker.cc index b3dd29bf9fb..7baa6f6b80f 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -362,8 +362,10 @@ void Worker::Run() { { int exit_code; bool stopped = is_stopped(); - if (!stopped) + if (!stopped) { + env_->VerifyNoStrongBaseObjects(); exit_code = EmitExit(env_.get()); + } Mutex::ScopedLock lock(mutex_); if (exit_code_ == 0 && !stopped) exit_code_ = exit_code; @@ -714,6 +716,12 @@ void Worker::MemoryInfo(MemoryTracker* tracker) const { tracker->TrackField("parent_port", parent_port_); } +bool Worker::IsNotIndicativeOfMemoryLeakAtExit() const { + // Worker objects always stay alive as long as the child thread, regardless + // of whether they are being referenced in the parent thread. + return true; +} + class WorkerHeapSnapshotTaker : public AsyncWrap { public: WorkerHeapSnapshotTaker(Environment* env, Local<Object> obj) |