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:
parent
00693bab30
commit
b1d1ac6524
7 changed files with 58 additions and 36 deletions
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue