mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-06 02:55:49 +03:00
LibC: Prevent assertions in malloc/free at exit time
This is a bit sad, but, with the Allocators as static globals their destructors were running before some user code. Which doesn't really make much sense, as none of the members of (at least the basic one) do any real heavy lifting or have many resources to RAII. To avoid the problem, just mmap the memory for the global arrays of Allocators in __malloc_init and let the Kernel collect the memory when we're done with the process.
This commit is contained in:
parent
7edfdca4b2
commit
150837e7e8
Notes:
sideshowbarker
2024-07-19 10:46:30 +09:00
Author: https://github.com/ADKaster Commit: https://github.com/SerenityOS/serenity/commit/150837e7e83 Pull-request: https://github.com/SerenityOS/serenity/pull/894
@ -3,6 +3,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//#define GLOBAL_DTORS_DEBUG
|
||||
|
||||
extern "C" {
|
||||
|
||||
int main(int, char**, char**);
|
||||
@ -83,11 +85,18 @@ void __cxa_finalize(void* dso_handle)
|
||||
|
||||
int entry_index = __exit_entry_count;
|
||||
|
||||
#ifdef GLOBAL_DTORS_DEBUG
|
||||
dbgprintf("__cxa_finalize: %d entries in the finalizer list\n", entry_index);
|
||||
#endif
|
||||
|
||||
while (--entry_index >= 0)
|
||||
{
|
||||
auto& exit_entry = __exit_entries[entry_index];
|
||||
bool needs_calling = !exit_entry.has_been_called && (!dso_handle || dso_handle == exit_entry.dso_handle);
|
||||
if (needs_calling) {
|
||||
#ifdef GLOBAL_DTORS_DEBUG
|
||||
dbgprintf("__cxa_finalize: calling entry[%d] %p(%p) dso: %p\n", entry_index, exit_entry.method, exit_entry.parameter, exit_entry.dso_handle);
|
||||
#endif
|
||||
exit_entry.method(exit_entry.parameter);
|
||||
exit_entry.has_been_called = true;
|
||||
}
|
||||
|
@ -99,8 +99,9 @@ struct BigAllocator {
|
||||
Vector<BigAllocationBlock*, number_of_big_blocks_to_keep_around_per_size_class> blocks;
|
||||
};
|
||||
|
||||
static Allocator g_allocators[num_size_classes];
|
||||
static BigAllocator g_big_allocators[1];
|
||||
// Allocators will be mmapped in __malloc_init
|
||||
Allocator* g_allocators = nullptr;
|
||||
BigAllocator* g_big_allocators = nullptr;
|
||||
|
||||
static Allocator* allocator_for_size(size_t size, size_t& good_size)
|
||||
{
|
||||
@ -369,5 +370,18 @@ void __malloc_init()
|
||||
s_scrub_free = false;
|
||||
if (getenv("LIBC_LOG_MALLOC"))
|
||||
s_log_malloc = true;
|
||||
|
||||
g_allocators = (Allocator*)mmap_with_name(nullptr, sizeof(Allocator) * num_size_classes, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, "LibC Allocators");
|
||||
for (size_t i = 0; i < num_size_classes; ++i) {
|
||||
new (&g_allocators[i]) Allocator();
|
||||
g_allocators[i].size = size_classes[i];
|
||||
}
|
||||
|
||||
g_big_allocators = (BigAllocator*)mmap_with_name(nullptr, sizeof(BigAllocator), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, "LibC BigAllocators");
|
||||
new (g_big_allocators) (BigAllocator);
|
||||
|
||||
// We could mprotect the mmaps here with atexit, but, since this method is called in _start before
|
||||
// _init and __init_array entries, our mprotect method would always be the last thing run before _exit.
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user