Merge pull request #8811 from electron/clean-node-on-exit

Clean up node Environment on exit
This commit is contained in:
Cheng Zhao 2017-03-06 20:36:59 +09:00 committed by GitHub
commit aaa8e81cd4
9 changed files with 57 additions and 6 deletions

View file

@ -132,6 +132,7 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
// Create the global environment. // Create the global environment.
node::Environment* env = node::Environment* env =
node_bindings_->CreateEnvironment(js_env_->context()); node_bindings_->CreateEnvironment(js_env_->context());
node_env_.reset(new NodeEnvironment(env));
// Make sure node can get correct environment when debugging. // Make sure node can get correct environment when debugging.
if (node_debugger_->IsRunning()) if (node_debugger_->IsRunning())

View file

@ -22,6 +22,7 @@ class Browser;
class JavascriptEnvironment; class JavascriptEnvironment;
class NodeBindings; class NodeBindings;
class NodeDebugger; class NodeDebugger;
class NodeEnvironment;
class BridgeTaskRunner; class BridgeTaskRunner;
class AtomBrowserMainParts : public brightray::BrowserMainParts { class AtomBrowserMainParts : public brightray::BrowserMainParts {
@ -79,6 +80,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
std::unique_ptr<Browser> browser_; std::unique_ptr<Browser> browser_;
std::unique_ptr<JavascriptEnvironment> js_env_; std::unique_ptr<JavascriptEnvironment> js_env_;
std::unique_ptr<NodeEnvironment> node_env_;
std::unique_ptr<NodeBindings> node_bindings_; std::unique_ptr<NodeBindings> node_bindings_;
std::unique_ptr<AtomBindings> atom_bindings_; std::unique_ptr<AtomBindings> atom_bindings_;
std::unique_ptr<NodeDebugger> node_debugger_; std::unique_ptr<NodeDebugger> node_debugger_;

View file

@ -12,6 +12,8 @@
#include "gin/array_buffer.h" #include "gin/array_buffer.h"
#include "gin/v8_initializer.h" #include "gin/v8_initializer.h"
#include "atom/common/node_includes.h"
namespace atom { namespace atom {
JavascriptEnvironment::JavascriptEnvironment() JavascriptEnvironment::JavascriptEnvironment()
@ -46,4 +48,11 @@ bool JavascriptEnvironment::Initialize() {
return true; return true;
} }
NodeEnvironment::NodeEnvironment(node::Environment* env) : env_(env) {
}
NodeEnvironment::~NodeEnvironment() {
node::FreeEnvironment(env_);
}
} // namespace atom } // namespace atom

View file

@ -8,8 +8,13 @@
#include "base/macros.h" #include "base/macros.h"
#include "gin/public/isolate_holder.h" #include "gin/public/isolate_holder.h"
namespace node {
class Environment;
}
namespace atom { namespace atom {
// Manage the V8 isolate and context automatically.
class JavascriptEnvironment { class JavascriptEnvironment {
public: public:
JavascriptEnvironment(); JavascriptEnvironment();
@ -37,6 +42,18 @@ class JavascriptEnvironment {
DISALLOW_COPY_AND_ASSIGN(JavascriptEnvironment); DISALLOW_COPY_AND_ASSIGN(JavascriptEnvironment);
}; };
// Manage the Node Environment automatically.
class NodeEnvironment {
public:
explicit NodeEnvironment(node::Environment* env);
~NodeEnvironment();
private:
node::Environment* env_;
DISALLOW_COPY_AND_ASSIGN(NodeEnvironment);
};
} // namespace atom } // namespace atom
#endif // ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_ #endif // ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_

View file

@ -84,6 +84,7 @@ AtomBindings::AtomBindings() {
} }
AtomBindings::~AtomBindings() { AtomBindings::~AtomBindings() {
uv_close(reinterpret_cast<uv_handle_t*>(&call_next_tick_async_), nullptr);
} }
void AtomBindings::BindTo(v8::Isolate* isolate, void AtomBindings::BindTo(v8::Isolate* isolate,
@ -117,6 +118,13 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
} }
} }
void AtomBindings::EnvironmentDestroyed(node::Environment* env) {
auto it = std::find(pending_next_ticks_.begin(), pending_next_ticks_.end(),
env);
if (it != pending_next_ticks_.end())
pending_next_ticks_.erase(it);
}
void AtomBindings::ActivateUVLoop(v8::Isolate* isolate) { void AtomBindings::ActivateUVLoop(v8::Isolate* isolate) {
node::Environment* env = node::Environment::GetCurrent(isolate); node::Environment* env = node::Environment::GetCurrent(isolate);
if (std::find(pending_next_ticks_.begin(), pending_next_ticks_.end(), env) != if (std::find(pending_next_ticks_.begin(), pending_next_ticks_.end(), env) !=

View file

@ -27,6 +27,9 @@ class AtomBindings {
// load native code from Electron instead. // load native code from Electron instead.
void BindTo(v8::Isolate* isolate, v8::Local<v8::Object> process); void BindTo(v8::Isolate* isolate, v8::Local<v8::Object> process);
// Should be called when a node::Environment has been destroyed.
void EnvironmentDestroyed(node::Environment* env);
static void Log(const base::string16& message); static void Log(const base::string16& message);
static void Crash(); static void Crash();

View file

@ -117,6 +117,7 @@ NodeBindings::~NodeBindings() {
// Clear uv. // Clear uv.
uv_sem_destroy(&embed_sem_); uv_sem_destroy(&embed_sem_);
uv_close(reinterpret_cast<uv_handle_t*>(&dummy_uv_handle_), nullptr);
} }
void NodeBindings::Initialize() { void NodeBindings::Initialize() {

View file

@ -213,7 +213,8 @@ std::vector<std::string> ParseSchemesCLISwitch(const char* switch_name) {
} // namespace } // namespace
AtomRendererClient::AtomRendererClient() AtomRendererClient::AtomRendererClient()
: node_bindings_(NodeBindings::Create(false)), : node_integration_initialized_(false),
node_bindings_(NodeBindings::Create(false)),
atom_bindings_(new AtomBindings) { atom_bindings_(new AtomBindings) {
isolated_world_ = base::CommandLine::ForCurrentProcess()->HasSwitch( isolated_world_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kContextIsolation); switches::kContextIsolation);
@ -349,11 +350,9 @@ void AtomRendererClient::DidCreateScriptContext(
if (!render_frame->IsMainFrame() && !IsDevToolsExtension(render_frame)) if (!render_frame->IsMainFrame() && !IsDevToolsExtension(render_frame))
return; return;
// Whether the node binding has been initialized.
bool first_time = node_bindings_->uv_env() == nullptr;
// Prepare the node bindings. // Prepare the node bindings.
if (first_time) { if (!node_integration_initialized_) {
node_integration_initialized_ = true;
node_bindings_->Initialize(); node_bindings_->Initialize();
node_bindings_->PrepareMessageLoop(); node_bindings_->PrepareMessageLoop();
} }
@ -369,7 +368,7 @@ void AtomRendererClient::DidCreateScriptContext(
// Load everything. // Load everything.
node_bindings_->LoadEnvironment(env); node_bindings_->LoadEnvironment(env);
if (first_time) { if (node_bindings_->uv_env() == nullptr) {
// Make uv loop being wrapped by window context. // Make uv loop being wrapped by window context.
node_bindings_->set_uv_env(env); node_bindings_->set_uv_env(env);
@ -388,6 +387,14 @@ void AtomRendererClient::WillReleaseScriptContext(
node::Environment* env = node::Environment::GetCurrent(context); node::Environment* env = node::Environment::GetCurrent(context);
if (env) if (env)
mate::EmitEvent(env->isolate(), env->process_object(), "exit"); mate::EmitEvent(env->isolate(), env->process_object(), "exit");
// The main frame may be replaced.
if (env == node_bindings_->uv_env())
node_bindings_->set_uv_env(nullptr);
// Destroy the node environment.
node::FreeEnvironment(env);
atom_bindings_->EnvironmentDestroyed(env);
} }
bool AtomRendererClient::ShouldFork(blink::WebLocalFrame* frame, bool AtomRendererClient::ShouldFork(blink::WebLocalFrame* frame,

View file

@ -66,6 +66,9 @@ class AtomRendererClient : public content::ContentRendererClient {
std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems)
override; override;
// Whether the node integration has been initialized.
bool node_integration_initialized_;
std::unique_ptr<NodeBindings> node_bindings_; std::unique_ptr<NodeBindings> node_bindings_;
std::unique_ptr<AtomBindings> atom_bindings_; std::unique_ptr<AtomBindings> atom_bindings_;
std::unique_ptr<PreferencesManager> preferences_manager_; std::unique_ptr<PreferencesManager> preferences_manager_;