diff --git a/atom/app/atom_main.cc b/atom/app/atom_main.cc index 47be348522f1..26dcb9421266 100644 --- a/atom/app/atom_main.cc +++ b/atom/app/atom_main.cc @@ -33,6 +33,7 @@ #include "atom/app/node_main.h" #include "atom/common/atom_command_line.h" +#include "base/at_exit.h" #include "base/i18n/icu_util.h" #if defined(OS_WIN) @@ -134,6 +135,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { if (env->GetVar("ATOM_SHELL_INTERNAL_RUN_AS_NODE", &node_indicator) && node_indicator == "1") { // Now that argv conversion is done, we can finally start. + base::AtExitManager atexit_manager; base::i18n::InitializeICU(); return atom::NodeMain(argc, argv); } else if (env->GetVar("ATOM_SHELL_INTERNAL_CRASH_SERVICE", @@ -165,6 +167,7 @@ int main(int argc, const char* argv[]) { char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE"); if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) { base::i18n::InitializeICU(); + base::AtExitManager atexit_manager; return atom::NodeMain(argc, const_cast(argv)); } diff --git a/atom/app/node_main.cc b/atom/app/node_main.cc index 356fe03e139d..7efb1b40eece 100644 --- a/atom/app/node_main.cc +++ b/atom/app/node_main.cc @@ -4,10 +4,12 @@ #include "atom/app/node_main.h" +#include "atom/app/uv_task_runner.h" #include "atom/browser/javascript_environment.h" #include "atom/browser/node_debugger.h" #include "atom/common/node_includes.h" #include "base/command_line.h" +#include "base/thread_task_runner_handle.h" #include "gin/array_buffer.h" #include "gin/public/isolate_holder.h" #include "gin/v8_initializer.h" @@ -24,14 +26,20 @@ int NodeMain(int argc, char *argv[]) { int exit_code = 1; { + // Feed gin::PerIsolateData with a task runner. + uv_loop_t* loop = uv_default_loop(); + scoped_refptr uv_task_runner(new UvTaskRunner(loop)); + base::ThreadTaskRunnerHandle handle(uv_task_runner); + gin::V8Initializer::LoadV8Snapshot(); + gin::V8Initializer::LoadV8Natives(); gin::IsolateHolder::Initialize( gin::IsolateHolder::kNonStrictMode, gin::ArrayBufferAllocator::SharedInstance()); JavascriptEnvironment gin_env; node::Environment* env = node::CreateEnvironment( - gin_env.isolate(), uv_default_loop(), gin_env.context(), argc, argv, + gin_env.isolate(), loop, gin_env.context(), argc, argv, exec_argc, exec_argv); // Start our custom debugger implementation. diff --git a/atom/app/uv_task_runner.cc b/atom/app/uv_task_runner.cc new file mode 100644 index 000000000000..23463e44e2ef --- /dev/null +++ b/atom/app/uv_task_runner.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/app/uv_task_runner.h" + +#include "base/stl_util.h" + +namespace atom { + +UvTaskRunner::UvTaskRunner(uv_loop_t* loop) : loop_(loop) { +} + +UvTaskRunner::~UvTaskRunner() { + for (auto& iter : tasks_) { + uv_unref(reinterpret_cast(iter.first)); + delete iter.first; + } +} + +bool UvTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) { + uv_timer_t* timer = new uv_timer_t; + timer->data = this; + uv_timer_init(loop_, timer); + uv_timer_start(timer, UvTaskRunner::OnTimeout, delay.InMilliseconds(), 0); + tasks_[timer] = task; + return true; +} + +bool UvTaskRunner::RunsTasksOnCurrentThread() const { + return true; +} + +bool UvTaskRunner::PostNonNestableDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) { + return PostDelayedTask(from_here, task, delay);; +} + +// static +void UvTaskRunner::OnTimeout(uv_timer_t* timer) { + UvTaskRunner* self = static_cast(timer->data); + if (!ContainsKey(self->tasks_, timer)) + return; + + self->tasks_[timer].Run(); + self->tasks_.erase(timer); + uv_unref(reinterpret_cast(timer)); + delete timer; +} + +} // namespace atom diff --git a/atom/app/uv_task_runner.h b/atom/app/uv_task_runner.h new file mode 100644 index 000000000000..e4eac0155354 --- /dev/null +++ b/atom/app/uv_task_runner.h @@ -0,0 +1,44 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_APP_UV_TASK_RUNNER_H_ +#define ATOM_APP_UV_TASK_RUNNER_H_ + +#include + +#include "base/callback.h" +#include "base/single_thread_task_runner.h" +#include "vendor/node/deps/uv/include/uv.h" + +namespace atom { + +// TaskRunner implementation that posts tasks into libuv's default loop. +class UvTaskRunner : public base::SingleThreadTaskRunner { + public: + explicit UvTaskRunner(uv_loop_t* loop); + ~UvTaskRunner() override; + + // base::SingleThreadTaskRunner: + bool PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool RunsTasksOnCurrentThread() const override; + bool PostNonNestableDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + + private: + static void OnTimeout(uv_timer_t* timer); + + uv_loop_t* loop_; + + std::map tasks_; + + DISALLOW_COPY_AND_ASSIGN(UvTaskRunner); +}; + +} // namespace atom + +#endif // ATOM_APP_UV_TASK_RUNNER_H_ diff --git a/atom/browser/bridge_task_runner.h b/atom/browser/bridge_task_runner.h index 01bde48eb805..fb42aa3852f9 100644 --- a/atom/browser/bridge_task_runner.h +++ b/atom/browser/bridge_task_runner.h @@ -14,7 +14,7 @@ namespace atom { class BridgeTaskRunner : public base::SingleThreadTaskRunner { public: BridgeTaskRunner() {} - ~BridgeTaskRunner() {} + ~BridgeTaskRunner() override {} // base::SingleThreadTaskRunner: bool PostDelayedTask(const tracked_objects::Location& from_here, diff --git a/filenames.gypi b/filenames.gypi index 3ea01274cf71..807ccd32bb66 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -62,6 +62,8 @@ 'atom/app/atom_main_delegate_mac.mm', 'atom/app/node_main.cc', 'atom/app/node_main.h', + 'atom/app/uv_task_runner.cc', + 'atom/app/uv_task_runner.h', 'atom/browser/api/atom_api_app.cc', 'atom/browser/api/atom_api_app.h', 'atom/browser/api/atom_api_auto_updater.cc',