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

fix: uv_walk crash on web worker close #24464

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 21 additions & 19 deletions shell/common/node_bindings.cc
Expand Up @@ -103,25 +103,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);

// 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;
int error = uv_loop_close(loop);

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;
Expand Down Expand Up @@ -228,6 +228,7 @@ NodeBindings::~NodeBindings() {
// Quit the embed thread.
embed_closed_ = true;
uv_sem_post(&embed_sem_);

WakeupEmbedThread();

// Wait for everything to be done.
Expand All @@ -238,7 +239,7 @@ NodeBindings::~NodeBindings() {
uv_close(reinterpret_cast<uv_handle_t*>(&dummy_uv_handle_), nullptr);

// Clean up worker loop
if (uv_loop_ == &worker_loop_)
if (in_worker_loop())
stop_and_close_uv_loop(uv_loop_);
}

Expand Down Expand Up @@ -439,7 +440,8 @@ void NodeBindings::WakeupMainThread() {
}

void NodeBindings::WakeupEmbedThread() {
uv_async_send(&dummy_uv_handle_);
if (!in_worker_loop())
uv_async_send(&dummy_uv_handle_);
}

// static
Expand Down
2 changes: 2 additions & 0 deletions shell/common/node_bindings.h
Expand Up @@ -62,6 +62,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);

Expand Down