Make Archive thread safe

This commit is contained in:
Cheng Zhao 2017-03-10 17:33:27 +09:00
parent c068285ff8
commit e496e18f6e
6 changed files with 22 additions and 5 deletions

View 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

View 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) {

View 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,

View 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"

View 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() {

View 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;
}