fix: change ASAR archive cache to per-process to fix leak (#29293)

* fix: change ASAR archive cache to per-process to fix leak (#29292)

* chore: address code review comments

* chore: tighten up thread-safety

* chore: better address code review comments

* chore: more code review changes
This commit is contained in:
David Sanders 2021-06-03 18:49:08 -07:00 committed by GitHub
parent 00693bab30
commit b1d1ac6524
7 changed files with 58 additions and 36 deletions

View file

@ -6,11 +6,14 @@
#include <map>
#include <string>
#include <utility>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/no_destructor.h"
#include "base/stl_util.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_local.h"
#include "base/threading/thread_restrictions.h"
#include "shell/common/asar/archive.h"
@ -19,30 +22,41 @@ namespace asar {
namespace {
// The global instance of ArchiveMap, will be destroyed on exit.
typedef std::map<base::FilePath, std::shared_ptr<Archive>> ArchiveMap;
base::LazyInstance<base::ThreadLocalPointer<ArchiveMap>>::Leaky
g_archive_map_tls = LAZY_INSTANCE_INITIALIZER;
const base::FilePath::CharType kAsarExtension[] = FILE_PATH_LITERAL(".asar");
std::map<base::FilePath, bool> g_is_directory_cache;
bool IsDirectoryCached(const base::FilePath& path) {
auto it = g_is_directory_cache.find(path);
if (it != g_is_directory_cache.end()) {
static base::NoDestructor<std::map<base::FilePath, bool>>
s_is_directory_cache;
static base::NoDestructor<base::Lock> lock;
base::AutoLock auto_lock(*lock);
auto& is_directory_cache = *s_is_directory_cache;
auto it = is_directory_cache.find(path);
if (it != is_directory_cache.end()) {
return it->second;
}
base::ThreadRestrictions::ScopedAllowIO allow_io;
return g_is_directory_cache[path] = base::DirectoryExists(path);
return is_directory_cache[path] = base::DirectoryExists(path);
}
} // namespace
ArchiveMap& GetArchiveCache() {
static base::NoDestructor<ArchiveMap> s_archive_map;
return *s_archive_map;
}
base::Lock& GetArchiveCacheLock() {
static base::NoDestructor<base::Lock> lock;
return *lock;
}
std::shared_ptr<Archive> GetOrCreateAsarArchive(const base::FilePath& path) {
if (!g_archive_map_tls.Pointer()->Get())
g_archive_map_tls.Pointer()->Set(new ArchiveMap);
ArchiveMap& map = *g_archive_map_tls.Pointer()->Get();
base::AutoLock auto_lock(GetArchiveCacheLock());
ArchiveMap& map = GetArchiveCache();
// if we have it, return it
const auto lower = map.lower_bound(path);
@ -61,8 +75,10 @@ std::shared_ptr<Archive> GetOrCreateAsarArchive(const base::FilePath& path) {
}
void ClearArchives() {
if (g_archive_map_tls.Pointer()->Get())
delete g_archive_map_tls.Pointer()->Get();
base::AutoLock auto_lock(GetArchiveCacheLock());
ArchiveMap& map = GetArchiveCache();
map.clear();
}
bool GetAsarArchivePath(const base::FilePath& full_path,