From 6cfbee9f34e69f5791e04b9aff70b165bbaa6848 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Wed, 8 Jul 2020 11:00:43 -0700 Subject: [PATCH] fix: uv_walk crash on web worker close (#24436) * fix: uv_walk crash on web worker close * Use DCHECK_EQ --- shell/common/node_bindings.cc | 38 ++++++++++++++++++----------------- shell/common/node_bindings.h | 2 ++ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/shell/common/node_bindings.cc b/shell/common/node_bindings.cc index 2f4c29f4405f..3e31ed9fb90a 100644 --- a/shell/common/node_bindings.cc +++ b/shell/common/node_bindings.cc @@ -96,25 +96,25 @@ ELECTRON_DESKTOP_CAPTURER_MODULE(V) namespace { void stop_and_close_uv_loop(uv_loop_t* loop) { - // Close any active handles uv_stop(loop); - uv_walk( - loop, - [](uv_handle_t* handle, void*) { - if (!uv_is_closing(handle)) { - uv_close(handle, nullptr); - } - }, - nullptr); + int error = uv_loop_close(loop); - // Run the loop to let it finish all the closing handles - // NB: after uv_stop(), uv_run(UV_RUN_DEFAULT) returns 0 when that's done - for (;;) - if (!uv_run(loop, UV_RUN_DEFAULT)) - break; + while (error) { + uv_run(loop, UV_RUN_DEFAULT); + uv_stop(loop); + uv_walk( + loop, + [](uv_handle_t* handle, void*) { + if (!uv_is_closing(handle)) { + uv_close(handle, nullptr); + } + }, + nullptr); + uv_run(loop, UV_RUN_DEFAULT); + error = uv_loop_close(loop); + } - DCHECK(!uv_loop_alive(loop)); - uv_loop_close(loop); + DCHECK_EQ(error, 0); } bool g_is_initialized = false; @@ -274,6 +274,7 @@ NodeBindings::~NodeBindings() { // Quit the embed thread. embed_closed_ = true; uv_sem_post(&embed_sem_); + WakeupEmbedThread(); // Wait for everything to be done. @@ -284,7 +285,7 @@ NodeBindings::~NodeBindings() { uv_close(reinterpret_cast(&dummy_uv_handle_), nullptr); // Clean up worker loop - if (uv_loop_ == &worker_loop_) + if (in_worker_loop()) stop_and_close_uv_loop(uv_loop_); } @@ -501,7 +502,8 @@ void NodeBindings::WakeupMainThread() { } void NodeBindings::WakeupEmbedThread() { - uv_async_send(&dummy_uv_handle_); + if (!in_worker_loop()) + uv_async_send(&dummy_uv_handle_); } // static diff --git a/shell/common/node_bindings.h b/shell/common/node_bindings.h index 65af54ce2aff..bf737a51ddff 100644 --- a/shell/common/node_bindings.h +++ b/shell/common/node_bindings.h @@ -58,6 +58,8 @@ class NodeBindings { uv_loop_t* uv_loop() const { return uv_loop_; } + bool in_worker_loop() const { return uv_loop_ == &worker_loop_; } + protected: explicit NodeBindings(BrowserEnvironment browser_env);