Skip to content

Commit 6fbab72

Browse files
committed
src: track handle cleanup per thread, not per IsolateData
The FreeEnvironment() fix for sibling Environments keeps the depth of nested Environment::CleanupHandles() calls on the IsolateData, so that InternalCallbackScope can re-allow JavaScript for sibling Environments while one of them is being freed. Environments that each have their own IsolateData on the same isolate and loop never see that counter and still fail with "illegal access". Environments that share a loop share a thread, so keep the depth in a thread_local instead. Refs: #65977 Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com> PR-URL: #66239 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 524eb24 commit 6fbab72

4 files changed

Lines changed: 10 additions & 9 deletions

File tree

‎src/api/callback.cc‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ InternalCallbackScope::InternalCallbackScope(
9696
}
9797

9898
Isolate* isolate = env->isolate();
99-
// See IsolateData::handle_cleanup_depth.
100-
if (env->isolate_data()->handle_cleanup_depth > 0) allow_js_.emplace(isolate);
99+
if (handle_cleanup_depth > 0) allow_js_.emplace(isolate);
101100

102101
HandleScope handle_scope(isolate);
103102
Local<Context> current_context = isolate->GetCurrentContext();

‎src/env.cc‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,8 @@ void Environment::ClosePerEnvHandles() {
14671467
close_and_finish(reinterpret_cast<uv_handle_t*>(&task_queues_async_));
14681468
}
14691469

1470+
thread_local int handle_cleanup_depth = 0;
1471+
14701472
void Environment::CleanupHandles() {
14711473
{
14721474
Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
@@ -1484,8 +1486,8 @@ void Environment::CleanupHandles() {
14841486
for (HandleWrap* handle : handle_wrap_queue_)
14851487
handle->Close();
14861488

1487-
isolate_data()->handle_cleanup_depth++;
1488-
auto done = OnScopeLeave([&]() { isolate_data()->handle_cleanup_depth--; });
1489+
handle_cleanup_depth++;
1490+
auto done = OnScopeLeave([]() { handle_cleanup_depth--; });
14891491
while (handle_cleanup_waiting_ != 0 ||
14901492
request_waiting_ != 0 ||
14911493
!handle_wrap_queue_.IsEmpty()) {

‎src/env.h‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,6 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer {
182182
inline worker::Worker* worker_context() const;
183183
inline void set_worker_context(worker::Worker* context);
184184

185-
// Non-zero while an Environment on this isolate is closing its handles with
186-
// JS disallowed isolate-wide; InternalCallbackScope re-allows it for the
187-
// other Environments whose callbacks run in those loop turns.
188-
int handle_cleanup_depth = 0;
189-
190185
#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
191186
#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
192187
#define VS(PropertyName, StringValue) V(v8::String, PropertyName)

‎src/node_internals.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,11 @@ class InternalCallbackScope {
283283
std::optional<v8::Isolate::AllowJavascriptExecutionScope> allow_js_;
284284
};
285285

286+
// Non-zero while an Environment on this thread is closing its handles with JS
287+
// disallowed isolate-wide; InternalCallbackScope re-allows it for the other
288+
// Environments whose callbacks run in those loop turns.
289+
extern thread_local int handle_cleanup_depth;
290+
286291
class DebugSealHandleScope {
287292
public:
288293
explicit inline DebugSealHandleScope(v8::Isolate* isolate = nullptr)

0 commit comments

Comments
 (0)