Make Archive thread safe
authorCheng Zhao <zcbenz@gmail.com>
Fri, 10 Mar 2017 08:33:27 +0000 (17:33 +0900)
committerCheng Zhao <zcbenz@gmail.com>
Mon, 20 Mar 2017 19:52:46 +0000 (12:52 -0700)
atom/browser/atom_browser_main_parts.cc
atom/common/asar/asar_util.cc
atom/common/asar/asar_util.h
atom/common/native_mate_converters/callback.h
atom/renderer/atom_renderer_client.cc
atom/renderer/web_worker_observer.cc

index c175b3d..d3f8237 100644 (file)
@@ -14,6 +14,7 @@
 #include "atom/browser/javascript_environment.h"
 #include "atom/browser/node_debugger.h"
 #include "atom/common/api/atom_bindings.h"
+#include "atom/common/asar/asar_util.h"
 #include "atom/common/node_bindings.h"
 #include "atom/common/node_includes.h"
 #include "base/command_line.h"
@@ -71,6 +72,7 @@ AtomBrowserMainParts::AtomBrowserMainParts()
 }
 
 AtomBrowserMainParts::~AtomBrowserMainParts() {
+  asar::ClearArchives();
   // Leak the JavascriptEnvironment on exit.
   // This is to work around the bug that V8 would be waiting for background
   // tasks to finish on exit, while somehow it waits forever in Electron, more
index 1eee099..0ffbfc6 100644 (file)
@@ -12,6 +12,7 @@
 #include "base/files/file_util.h"
 #include "base/lazy_instance.h"
 #include "base/stl_util.h"
+#include "base/threading/thread_local.h"
 
 namespace asar {
 
@@ -19,14 +20,17 @@ namespace {
 
 // The global instance of ArchiveMap, will be destroyed on exit.
 typedef std::map<base::FilePath, std::shared_ptr<Archive>> ArchiveMap;
-static base::LazyInstance<ArchiveMap> g_archive_map = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::ThreadLocalPointer<ArchiveMap>>::Leaky
+    g_archive_map_tls = LAZY_INSTANCE_INITIALIZER;
 
 const base::FilePath::CharType kAsarExtension[] = FILE_PATH_LITERAL(".asar");
 
 }  // namespace
 
 std::shared_ptr<Archive> GetOrCreateAsarArchive(const base::FilePath& path) {
-  ArchiveMap& archive_map = *g_archive_map.Pointer();
+  if (!g_archive_map_tls.Pointer()->Get())
+    g_archive_map_tls.Pointer()->Set(new ArchiveMap);
+  ArchiveMap& archive_map = *g_archive_map_tls.Pointer()->Get();
   if (!ContainsKey(archive_map, path)) {
     std::shared_ptr<Archive> archive(new Archive(path));
     if (!archive->Init())
@@ -36,6 +40,11 @@ std::shared_ptr<Archive> GetOrCreateAsarArchive(const base::FilePath& path) {
   return archive_map[path];
 }
 
+void ClearArchives() {
+  if (g_archive_map_tls.Pointer()->Get())
+    delete g_archive_map_tls.Pointer()->Get();
+}
+
 bool GetAsarArchivePath(const base::FilePath& full_path,
                         base::FilePath* asar_path,
                         base::FilePath* relative_path) {
index 4cb5b88..90ffb9b 100644 (file)
@@ -19,6 +19,9 @@ class Archive;
 // Gets or creates a new Archive from the path.
 std::shared_ptr<Archive> GetOrCreateAsarArchive(const base::FilePath& path);
 
+// Destroy cached Archive objects.
+void ClearArchives();
+
 // Separates the path to Archive out.
 bool GetAsarArchivePath(const base::FilePath& full_path,
                         base::FilePath* asar_path,
index f42ee87..28bff3c 100644 (file)
@@ -10,8 +10,8 @@
 #include "atom/common/api/locker.h"
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/message_loop/message_loop.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "content/public/browser/browser_thread.h"
 #include "native_mate/function_template.h"
 #include "native_mate/scoped_persistent.h"
index 37a16ee..c4f739c 100644 (file)
@@ -13,6 +13,7 @@
 #include "atom/common/api/atom_bindings.h"
 #include "atom/common/api/event_emitter_caller.h"
 #include "atom/common/atom_constants.h"
+#include "atom/common/asar/asar_util.h"
 #include "atom/common/color_util.h"
 #include "atom/common/native_mate_converters/value_converter.h"
 #include "atom/common/node_bindings.h"
@@ -228,6 +229,7 @@ AtomRendererClient::AtomRendererClient()
 }
 
 AtomRendererClient::~AtomRendererClient() {
+  asar::ClearArchives();
 }
 
 void AtomRendererClient::RenderThreadStarted() {
index 323c9be..954b2f2 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "atom/common/api/atom_bindings.h"
 #include "atom/common/api/event_emitter_caller.h"
+#include "atom/common/asar/asar_util.h"
 #include "atom/common/node_bindings.h"
 #include "base/lazy_instance.h"
 #include "base/threading/thread_local.h"
@@ -35,6 +36,8 @@ WebWorkerObserver::WebWorkerObserver()
 
 WebWorkerObserver::~WebWorkerObserver() {
   lazy_tls.Pointer()->Set(nullptr);
+  node::FreeEnvironment(node_bindings_->uv_env());
+  asar::ClearArchives();
 }
 
 void WebWorkerObserver::ContextCreated(v8::Local<v8::Context> context) {
@@ -64,8 +67,6 @@ void WebWorkerObserver::ContextWillDestroy(v8::Local<v8::Context> context) {
   if (env)
     mate::EmitEvent(env->isolate(), env->process_object(), "exit");
 
-  // Destroy the node environment.
-  node::FreeEnvironment(env);
   delete this;
 }