Remove remaining NoDestructor usage
Replace remaining NoDestructor usage with allocations at PDFium library
initialization time, and corresponding deletions at library destruction
time.
Bug: pdfium:1876
Change-Id: I658cbe12ea37ceccace4cbef58a39dea37fa8110
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/116751
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/fx_memory.h b/core/fxcrt/fx_memory.h
index 477823c..c9fa991 100644
--- a/core/fxcrt/fx_memory.h
+++ b/core/fxcrt/fx_memory.h
@@ -31,6 +31,7 @@
#endif
void FX_InitializeMemoryAllocators();
+void FX_DestroyMemoryAllocators();
NOINLINE void FX_OutOfMemoryTerminate(size_t size);
// General Partition Allocators.
diff --git a/core/fxcrt/fx_memory_malloc.cpp b/core/fxcrt/fx_memory_malloc.cpp
index e199d42..bc958dd 100644
--- a/core/fxcrt/fx_memory_malloc.cpp
+++ b/core/fxcrt/fx_memory_malloc.cpp
@@ -68,6 +68,8 @@
void FX_InitializeMemoryAllocators() {}
+void FX_DestroyMemoryAllocators() {}
+
void* FX_ArrayBufferAllocate(size_t length) {
void* result = calloc(length, 1);
if (!result)
diff --git a/core/fxcrt/fx_memory_pa.cpp b/core/fxcrt/fx_memory_pa.cpp
index a30fc1a..be6e2af 100644
--- a/core/fxcrt/fx_memory_pa.cpp
+++ b/core/fxcrt/fx_memory_pa.cpp
@@ -8,7 +8,6 @@
#include "core/fxcrt/fx_safe_types.h"
#include "partition_alloc/partition_alloc.h"
-#include "third_party/base/no_destructor.h"
#if !defined(PDF_USE_PARTITION_ALLOC)
#error "File compiled under wrong build option."
@@ -18,24 +17,29 @@
constexpr partition_alloc::PartitionOptions kOptions = {};
+struct Allocators {
+#ifndef V8_ENABLE_SANDBOX
+ partition_alloc::PartitionAllocator array_buffer_allocator{kOptions};
+#endif
+
+ partition_alloc::PartitionAllocator general_allocator{kOptions};
+ partition_alloc::PartitionAllocator string_allocator{kOptions};
+};
+
+Allocators* g_allocators = nullptr;
+
#ifndef V8_ENABLE_SANDBOX
partition_alloc::PartitionAllocator& GetArrayBufferPartitionAllocator() {
- static pdfium::base::NoDestructor<partition_alloc::PartitionAllocator>
- s_array_buffer_allocator(kOptions);
- return *s_array_buffer_allocator;
+ return g_allocators->array_buffer_allocator;
}
-#endif // V8_ENABLE_SANDBOX
+#endif
partition_alloc::PartitionAllocator& GetGeneralPartitionAllocator() {
- static pdfium::base::NoDestructor<partition_alloc::PartitionAllocator>
- s_general_allocator(kOptions);
- return *s_general_allocator;
+ return g_allocators->general_allocator;
}
partition_alloc::PartitionAllocator& GetStringPartitionAllocator() {
- static pdfium::base::NoDestructor<partition_alloc::PartitionAllocator>
- s_string_allocator(kOptions);
- return *s_string_allocator;
+ return g_allocators->string_allocator;
}
} // namespace
@@ -122,20 +126,16 @@
} // namespace pdfium::internal
void FX_InitializeMemoryAllocators() {
- static bool s_partition_allocators_initialized = false;
- if (!s_partition_allocators_initialized) {
- partition_alloc::PartitionAllocGlobalInit(FX_OutOfMemoryTerminate);
- // These calls force the allocators to be created and initialized (via magic
- // of static local variables).
-#ifndef V8_ENABLE_SANDBOX
- GetArrayBufferPartitionAllocator();
-#endif // V8_ENABLE_SANDBOX
- GetGeneralPartitionAllocator();
- GetStringPartitionAllocator();
- s_partition_allocators_initialized = true;
+ if (!g_allocators) {
+ g_allocators = new Allocators();
}
}
+void FX_DestroyMemoryAllocators() {
+ delete g_allocators;
+ g_allocators = nullptr;
+}
+
#ifndef V8_ENABLE_SANDBOX
void* FX_ArrayBufferAllocate(size_t length) {
return GetArrayBufferPartitionAllocator()
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 1507230..0f0c6ac 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -57,7 +57,6 @@
#ifdef PDF_ENABLE_V8
#include "fxjs/cfx_v8_array_buffer_allocator.h"
-#include "third_party/base/no_destructor.h"
#endif
#ifdef PDF_ENABLE_XFA
@@ -274,6 +273,7 @@
CPDF_PageModule::Destroy();
CFX_GEModule::Destroy();
CFX_Timer::DestroyGlobals();
+ FX_DestroyMemoryAllocators();
g_bLibraryInitialized = false;
}
@@ -1151,8 +1151,11 @@
}
FPDF_EXPORT void* FPDF_CALLCONV FPDF_GetArrayBufferAllocatorSharedInstance() {
- static pdfium::base::NoDestructor<CFX_V8ArrayBufferAllocator> allocator;
- return allocator.get();
+ // Deliberately leaked. This allocator is used outside of the library
+ // initialization / destruction lifecycle, and the caller does not take
+ // ownership of the object. Thus there is no existing way to delete this.
+ static auto* s_allocator = new CFX_V8ArrayBufferAllocator();
+ return s_allocator;
}
#endif // PDF_ENABLE_V8
diff --git a/fpdfsdk/fpdf_view_embeddertest.cpp b/fpdfsdk/fpdf_view_embeddertest.cpp
index d708e8a..dc87b5f 100644
--- a/fpdfsdk/fpdf_view_embeddertest.cpp
+++ b/fpdfsdk/fpdf_view_embeddertest.cpp
@@ -2089,36 +2089,34 @@
FPDF_DestroyLibrary();
std::string agg_checksum;
+ const FPDF_LIBRARY_CONFIG kAggConfig = {
+ .version = 4,
+ .m_pUserFontPaths = nullptr,
+ .m_pIsolate = nullptr,
+ .m_v8EmbedderSlot = 0,
+ .m_pPlatform = nullptr,
+ .m_RendererType = FPDF_RENDERERTYPE_AGG,
+ };
+ FPDF_InitLibraryWithConfig(&kAggConfig);
{
- FPDF_LIBRARY_CONFIG config = {
- .version = 4,
- .m_pUserFontPaths = nullptr,
- .m_pIsolate = nullptr,
- .m_v8EmbedderSlot = 0,
- .m_pPlatform = nullptr,
- .m_RendererType = FPDF_RENDERERTYPE_AGG,
- };
- FPDF_InitLibraryWithConfig(&config);
-
ASSERT_TRUE(OpenDocument("rectangles.pdf"));
FPDF_PAGE page = LoadPage(0);
ScopedFPDFBitmap bitmap = RenderPage(page);
agg_checksum = HashBitmap(bitmap.get());
UnloadPage(page);
CloseDocument();
- FPDF_DestroyLibrary();
}
+ FPDF_DestroyLibrary();
std::string skia_checksum;
+ const FPDF_LIBRARY_CONFIG kSkiaConfig = {
+ .version = 2,
+ .m_pUserFontPaths = nullptr,
+ .m_pIsolate = nullptr,
+ .m_v8EmbedderSlot = 0,
+ };
+ FPDF_InitLibraryWithConfig(&kSkiaConfig);
{
- FPDF_LIBRARY_CONFIG config = {
- .version = 2,
- .m_pUserFontPaths = nullptr,
- .m_pIsolate = nullptr,
- .m_v8EmbedderSlot = 0,
- };
- FPDF_InitLibraryWithConfig(&config);
-
ASSERT_TRUE(OpenDocument("rectangles.pdf"));
FPDF_PAGE page = LoadPage(0);
ScopedFPDFBitmap bitmap = RenderPage(page);
diff --git a/public/fpdfview.h b/public/fpdfview.h
index 580c524..e1b3a32 100644
--- a/public/fpdfview.h
+++ b/public/fpdfview.h
@@ -1452,6 +1452,9 @@
// Use is optional, but allows external creation of isolates
// matching the ones PDFium will make when none is provided
// via |FPDF_LIBRARY_CONFIG::m_pIsolate|.
+//
+// Can only be called when the library is in an uninitialized or
+// destroyed state.
FPDF_EXPORT void* FPDF_CALLCONV FPDF_GetArrayBufferAllocatorSharedInstance();
#endif // PDF_ENABLE_V8
diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn
index f3f56d7..32fc813 100644
--- a/third_party/BUILD.gn
+++ b/third_party/BUILD.gn
@@ -556,7 +556,6 @@
"base/check_op.h",
"base/component_export.h",
"base/immediate_crash.h",
- "base/no_destructor.h",
"base/notreached.h",
"base/template_util.h",
]
diff --git a/third_party/base/no_destructor.h b/third_party/base/no_destructor.h
deleted file mode 100644
index 5d125a9..0000000
--- a/third_party/base/no_destructor.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BASE_NO_DESTRUCTOR_H_
-#define THIRD_PARTY_BASE_NO_DESTRUCTOR_H_
-
-#include <new>
-#include <type_traits>
-#include <utility>
-
-namespace pdfium {
-namespace base {
-
-// Helper type to create a function-local static variable of type `T` when `T`
-// has a non-trivial destructor. Storing a `T` in a `base::NoDestructor<T>` will
-// prevent `~T()` from running, even when the variable goes out of scope.
-//
-// Useful when a variable has static storage duration but its type has a
-// non-trivial destructor. Chromium bans global constructors and destructors:
-// using a function-local static variable prevents the former, while using
-// `base::NoDestructor<T>` prevents the latter.
-//
-// ## Caveats
-//
-// - Must only be used as a function-local static variable. Declaring a global
-// variable of type `base::NoDestructor<T>` will still generate a global
-// constructor; declaring a local or member variable will lead to memory leaks
-// or other surprising and undesirable behaviour.
-//
-// - If the data is rarely used, consider creating it on demand rather than
-// caching it for the lifetime of the program. Though `base::NoDestructor<T>`
-// does not heap allocate, the compiler still reserves space in bss for
-// storing `T`, which costs memory at runtime.
-//
-// - If `T` is trivially destructible, do not use `base::NoDestructor<T>`:
-//
-// const uint64_t GetUnstableSessionSeed() {
-// // No need to use `base::NoDestructor<T>` as `uint64_t` is trivially
-// // destructible and does not require a global destructor.
-// static const uint64_t kSessionSeed = base::RandUint64();
-// return kSessionSeed;
-// }
-//
-// ## Example Usage
-//
-// const std::string& GetDefaultText() {
-// // Required since `static const std::string` requires a global destructor.
-// static const base::NoDestructor<std::string> s("Hello world!");
-// return *s;
-// }
-//
-// More complex initialization using a lambda:
-//
-// const std::string& GetRandomNonce() {
-// // `nonce` is initialized with random data the first time this function is
-// // called, but its value is fixed thereafter.
-// static const base::NoDestructor<std::string> nonce([] {
-// std::string s(16);
-// crypto::RandString(s.data(), s.size());
-// return s;
-// }());
-// return *nonce;
-// }
-//
-// ## Thread safety
-//
-// Initialisation of function-local static variables is thread-safe since C++11.
-// The standard guarantees that:
-//
-// - function-local static variables will be initialised the first time
-// execution passes through the declaration.
-//
-// - if another thread's execution concurrently passes through the declaration
-// in the middle of initialisation, that thread will wait for the in-progress
-// initialisation to complete.
-template <typename T>
-class NoDestructor {
- public:
- static_assert(
- !std::is_trivially_destructible_v<T>,
- "T is trivially destructible; please use a function-local static "
- "of type T directly instead");
-
- // Not constexpr; just write static constexpr T x = ...; if the value should
- // be a constexpr.
- template <typename... Args>
- explicit NoDestructor(Args&&... args) {
- new (storage_) T(std::forward<Args>(args)...);
- }
-
- // Allows copy and move construction of the contained type, to allow
- // construction from an initializer list, e.g. for std::vector.
- explicit NoDestructor(const T& x) { new (storage_) T(x); }
- explicit NoDestructor(T&& x) { new (storage_) T(std::move(x)); }
-
- NoDestructor(const NoDestructor&) = delete;
- NoDestructor& operator=(const NoDestructor&) = delete;
-
- ~NoDestructor() = default;
-
- const T& operator*() const { return *get(); }
- T& operator*() { return *get(); }
-
- const T* operator->() const { return get(); }
- T* operator->() { return get(); }
-
- const T* get() const { return reinterpret_cast<const T*>(storage_); }
- T* get() { return reinterpret_cast<T*>(storage_); }
-
- private:
- alignas(T) char storage_[sizeof(T)];
-
-#if defined(LEAK_SANITIZER)
- // TODO(https://crbug.com/812277): This is a hack to work around the fact
- // that LSan doesn't seem to treat NoDestructor as a root for reachability
- // analysis. This means that code like this:
- // static base::NoDestructor<std::vector<int>> v({1, 2, 3});
- // is considered a leak. Using the standard leak sanitizer annotations to
- // suppress leaks doesn't work: std::vector is implicitly constructed before
- // calling the base::NoDestructor constructor.
- //
- // Unfortunately, I haven't been able to demonstrate this issue in simpler
- // reproductions: until that's resolved, hold an explicit pointer to the
- // placement-new'd object in leak sanitizer mode to help LSan realize that
- // objects allocated by the contained type are still reachable.
- T* storage_ptr_ = reinterpret_cast<T*>(storage_);
-#endif // defined(LEAK_SANITIZER)
-};
-
-} // namespace base
-} // namespace pdfium
-
-#endif // THIRD_PARTY_BASE_NO_DESTRUCTOR_H_