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: iocp integration when process is reused #33207

Merged
merged 1 commit into from Mar 21, 2022
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
13 changes: 2 additions & 11 deletions shell/common/node_bindings.cc
Expand Up @@ -462,7 +462,8 @@ node::Environment* NodeBindings::CreateEnvironment(

args.insert(args.begin() + 1, init_script);

isolate_data_ = node::CreateIsolateData(isolate, uv_loop_, platform);
if (!isolate_data_)
isolate_data_ = node::CreateIsolateData(isolate, uv_loop_, platform);

node::Environment* env;
uint64_t flags = node::EnvironmentFlags::kDefaultFlags |
Expand Down Expand Up @@ -573,16 +574,6 @@ void NodeBindings::LoadEnvironment(node::Environment* env) {
}

void NodeBindings::PrepareMessageLoop() {
#if !BUILDFLAG(IS_WIN)
int handle = uv_backend_fd(uv_loop_);

// If the backend fd hasn't changed, don't proceed.
if (handle == handle_)
return;

handle_ = handle;
#endif

// Add dummy handle for libuv, otherwise libuv would quit when there is
// nothing to do.
uv_async_init(uv_loop_, dummy_uv_handle_.get(), nullptr);
Expand Down
10 changes: 5 additions & 5 deletions shell/common/node_bindings.h
Expand Up @@ -93,11 +93,15 @@ class NodeBindings {
void LoadEnvironment(node::Environment* env);

// Prepare for message loop integration.
void PrepareMessageLoop();
virtual void PrepareMessageLoop();

// Do message loop integration.
virtual void RunMessageLoop();

// Gets/sets the per isolate data.
void set_isolate_data(node::IsolateData* isolate_data) {
isolate_data_ = isolate_data;
}
node::IsolateData* isolate_data() const { return isolate_data_; }

// Gets/sets the environment to wrap uv loop.
Expand Down Expand Up @@ -161,10 +165,6 @@ class NodeBindings {
// Isolate data used in creating the environment
node::IsolateData* isolate_data_ = nullptr;

#if !BUILDFLAG(IS_WIN)
int handle_ = -1;
#endif

base::WeakPtrFactory<NodeBindings> weak_factory_{this};
};

Expand Down
18 changes: 18 additions & 0 deletions shell/common/node_bindings_linux.cc
Expand Up @@ -19,7 +19,25 @@ NodeBindingsLinux::NodeBindingsLinux(BrowserEnvironment browser_env)

NodeBindingsLinux::~NodeBindingsLinux() = default;

void NodeBindingsLinux::PrepareMessageLoop() {
int handle = uv_backend_fd(uv_loop_);

// If the backend fd hasn't changed, don't proceed.
if (handle == handle_)
return;

NodeBindings::PrepareMessageLoop();
}

void NodeBindingsLinux::RunMessageLoop() {
int handle = uv_backend_fd(uv_loop_);

// If the backend fd hasn't changed, don't proceed.
if (handle == handle_)
return;

handle_ = handle;

// Get notified when libuv's watcher queue changes.
uv_loop_->data = this;
uv_loop_->on_watcher_queue_updated = OnWatcherQueueChanged;
Expand Down
4 changes: 4 additions & 0 deletions shell/common/node_bindings_linux.h
Expand Up @@ -15,6 +15,7 @@ class NodeBindingsLinux : public NodeBindings {
explicit NodeBindingsLinux(BrowserEnvironment browser_env);
~NodeBindingsLinux() override;

void PrepareMessageLoop() override;
void RunMessageLoop() override;

private:
Expand All @@ -25,6 +26,9 @@ class NodeBindingsLinux : public NodeBindings {

// Epoll to poll for uv's backend fd.
int epoll_;

// uv's backend fd.
int handle_ = -1;
};

} // namespace electron
Expand Down
18 changes: 18 additions & 0 deletions shell/common/node_bindings_mac.cc
Expand Up @@ -19,7 +19,25 @@ NodeBindingsMac::NodeBindingsMac(BrowserEnvironment browser_env)

NodeBindingsMac::~NodeBindingsMac() = default;

void NodeBindingsMac::PrepareMessageLoop() {
int handle = uv_backend_fd(uv_loop_);

// If the backend fd hasn't changed, don't proceed.
if (handle == handle_)
return;

NodeBindings::PrepareMessageLoop();
}

void NodeBindingsMac::RunMessageLoop() {
int handle = uv_backend_fd(uv_loop_);

// If the backend fd hasn't changed, don't proceed.
if (handle == handle_)
return;

handle_ = handle;

// Get notified when libuv's watcher queue changes.
uv_loop_->data = this;
uv_loop_->on_watcher_queue_updated = OnWatcherQueueChanged;
Expand Down
4 changes: 4 additions & 0 deletions shell/common/node_bindings_mac.h
Expand Up @@ -15,13 +15,17 @@ class NodeBindingsMac : public NodeBindings {
explicit NodeBindingsMac(BrowserEnvironment browser_env);
~NodeBindingsMac() override;

void PrepareMessageLoop() override;
void RunMessageLoop() override;

private:
// Called when uv's watcher queue changes.
static void OnWatcherQueueChanged(uv_loop_t* loop);

void PollEvents() override;

// uv's backend fd.
int handle_ = -1;
};

} // namespace electron
Expand Down
23 changes: 23 additions & 0 deletions shell/common/node_bindings_win.cc
Expand Up @@ -29,6 +29,29 @@ NodeBindingsWin::NodeBindingsWin(BrowserEnvironment browser_env)

NodeBindingsWin::~NodeBindingsWin() = default;

void NodeBindingsWin::PrepareMessageLoop() {
// IOCP does not change for the process until the loop is recreated,
// we ensure that there is only a single polling thread satisfying
// the concurrency limit set from CreateIoCompletionPort call by
// uv_loop_init for the lifetime of this process.
if (initialized_)
return;

NodeBindings::PrepareMessageLoop();
}

void NodeBindingsWin::RunMessageLoop() {
// Avoid calling UvRunOnce if the loop is already active,
// otherwise it can lead to situations were the number of active
// threads processing on IOCP is greater than the concurrency limit.
if (initialized_)
return;

initialized_ = true;

NodeBindings::RunMessageLoop();
}

void NodeBindingsWin::PollEvents() {
// If there are other kinds of events pending, uv_backend_timeout will
// instruct us not to wait.
Expand Down
6 changes: 6 additions & 0 deletions shell/common/node_bindings_win.h
Expand Up @@ -15,8 +15,14 @@ class NodeBindingsWin : public NodeBindings {
explicit NodeBindingsWin(BrowserEnvironment browser_env);
~NodeBindingsWin() override;

void PrepareMessageLoop() override;
void RunMessageLoop() override;

private:
void PollEvents() override;

// Indicates whether polling thread has been created.
bool initialized_ = false;
};

} // namespace electron
Expand Down
4 changes: 3 additions & 1 deletion shell/renderer/electron_renderer_client.cc
Expand Up @@ -162,8 +162,10 @@ void ElectronRendererClient::WillReleaseScriptContext(
isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);

node::FreeEnvironment(env);
if (env == node_bindings_->uv_env())
if (node_bindings_->uv_env() == nullptr) {
node::FreeIsolateData(node_bindings_->isolate_data());
node_bindings_->set_isolate_data(nullptr);
}

isolate->SetMicrotasksPolicy(old_policy);

Expand Down