diff options
author | Christopher Ferris <cferris@google.com> | 2016-03-17 17:52:54 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2016-03-17 17:52:55 +0000 |
commit | 5f1de52eca7d3892cec864d2dc46b1dfdecba891 (patch) | |
tree | 3e63994dd7b7866d3ce0e45beade95b6ddca47d1 /libc/malloc_debug/malloc_debug.cpp | |
parent | d057f449a0a3ad2f574d11ffce060d69db9fc019 (diff) | |
parent | d0919623a2ef56107590eca9a9522a250fb8bd4a (diff) |
Merge "Fix race in malloc debug option free_track."
Diffstat (limited to 'libc/malloc_debug/malloc_debug.cpp')
-rw-r--r-- | libc/malloc_debug/malloc_debug.cpp | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp index 568192d69..1ee76897d 100644 --- a/libc/malloc_debug/malloc_debug.cpp +++ b/libc/malloc_debug/malloc_debug.cpp @@ -112,6 +112,7 @@ static void InitAtfork() { ); }); } + static void LogTagError(const Header* header, const void* pointer, const char* name) { ScopedDisableDebugCalls disable; @@ -145,7 +146,7 @@ static void* InitHeader(Header* header, void* orig_pointer, size_t size) { return nullptr; } header->usable_size -= g_debug->pointer_offset() + - reinterpret_cast<uintptr_t>(orig_pointer) - reinterpret_cast<uintptr_t>(header); + reinterpret_cast<uintptr_t>(header) - reinterpret_cast<uintptr_t>(orig_pointer); if (g_debug->config().options & FRONT_GUARD) { uint8_t* guard = g_debug->GetFrontGuard(header); @@ -326,8 +327,9 @@ void debug_free(void* pointer) { void* free_pointer = pointer; size_t bytes; + Header* header; if (g_debug->need_header()) { - Header* header = g_debug->GetHeader(pointer); + header = g_debug->GetHeader(pointer); if (header->tag != DEBUG_TAG) { LogTagError(header, pointer, "free"); return; @@ -353,13 +355,6 @@ void debug_free(void* pointer) { } g_debug->track->Remove(header, backtrace_found); } - - if (g_debug->config().options & FREE_TRACK) { - g_debug->free_track->Add(*g_debug, header); - - // Do not free this pointer just yet. - free_pointer = nullptr; - } header->tag = DEBUG_FREE_TAG; bytes = header->usable_size; @@ -373,7 +368,16 @@ void debug_free(void* pointer) { memset(pointer, g_debug->config().fill_free_value, bytes); } - g_dispatch->free(free_pointer); + if (g_debug->config().options & FREE_TRACK) { + // Do not add the allocation until we are done modifying the pointer + // itself. This avoids a race if a lot of threads are all doing + // frees at the same time and we wind up trying to really free this + // pointer from another thread, while still trying to free it in + // this function. + g_debug->free_track->Add(*g_debug, header); + } else { + g_dispatch->free(free_pointer); + } } void* debug_memalign(size_t alignment, size_t bytes) { |