Skip to content

Commit fece197

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: nodejs#65977 Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
1 parent 6dfe4eb commit fece197

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
@@ -1436,6 +1436,8 @@ void Environment::ClosePerEnvHandles() {
14361436
close_and_finish(reinterpret_cast<uv_handle_t*>(&task_queues_async_));
14371437
}
14381438

1439+
thread_local int handle_cleanup_depth = 0;
1440+
14391441
void Environment::CleanupHandles() {
14401442
{
14411443
Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
@@ -1453,8 +1455,8 @@ void Environment::CleanupHandles() {
14531455
for (HandleWrap* handle : handle_wrap_queue_)
14541456
handle->Close();
14551457

1456-
isolate_data()->handle_cleanup_depth++;
1457-
auto done = OnScopeLeave([&]() { isolate_data()->handle_cleanup_depth--; });
1458+
handle_cleanup_depth++;
1459+
auto done = OnScopeLeave([]() { handle_cleanup_depth--; });
14581460
while (handle_cleanup_waiting_ != 0 ||
14591461
request_waiting_ != 0 ||
14601462
!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)