Fix allocation_tracker crashes
Use C++ unordered_map in allocation_tracker.
Bug: 28888632
Change-Id: I15204b0bede5686af25fc6cdd05ce3097b436dd6
diff --git a/osi/Android.mk b/osi/Android.mk
index cd6dee6..eac2437 100644
--- a/osi/Android.mk
+++ b/osi/Android.mk
@@ -25,7 +25,7 @@
# dependencies are abstracted.
btosiCommonSrc := \
./src/alarm.c \
- ./src/allocation_tracker.c \
+ ./src/allocation_tracker.cc \
./src/allocator.c \
./src/array.c \
./src/buffer.c \
diff --git a/osi/BUILD.gn b/osi/BUILD.gn
index abb2fa8..dcb02a1 100644
--- a/osi/BUILD.gn
+++ b/osi/BUILD.gn
@@ -17,7 +17,7 @@
static_library("osi") {
sources = [
"src/alarm.c",
- "src/allocation_tracker.c",
+ "src/allocation_tracker.cc",
"src/allocator.c",
"src/array.c",
"src/buffer.c",
diff --git a/osi/src/allocation_tracker.c b/osi/src/allocation_tracker.cc
similarity index 64%
rename from osi/src/allocation_tracker.c
rename to osi/src/allocation_tracker.cc
index b4e1a84..c4f9705 100644
--- a/osi/src/allocation_tracker.c
+++ b/osi/src/allocation_tracker.cc
@@ -24,10 +24,9 @@
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
+#include <unordered_map>
#include "osi/include/allocator.h"
-#include "osi/include/hash_functions.h"
-#include "osi/include/hash_map.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -38,77 +37,58 @@
bool freed;
} allocation_t;
-// Hidden constructor for hash map for our use only. Everything else should use the
-// normal interface.
-hash_map_t *hash_map_new_internal(
- size_t size,
- hash_index_fn hash_fn,
- key_free_fn key_fn,
- data_free_fn,
- key_equality_fn equality_fn,
- const allocator_t *zeroed_allocator);
-
-static bool allocation_entry_freed_checker(hash_map_entry_t *entry, void *context);
-static void *untracked_calloc(size_t size);
-
-static const size_t allocation_hash_map_size = 1024;
static const char *canary = "tinybird";
-static const allocator_t untracked_calloc_allocator = {
- untracked_calloc,
- free
-};
static size_t canary_size;
-static hash_map_t *allocations;
+static std::unordered_map<void*, allocation_t*> allocations;
static pthread_mutex_t lock;
+static bool enabled = false;
void allocation_tracker_init(void) {
- if (allocations)
- return;
-
canary_size = strlen(canary);
pthread_mutex_init(&lock, NULL);
pthread_mutex_lock(&lock);
- allocations = hash_map_new_internal(
- allocation_hash_map_size,
- hash_function_pointer,
- NULL,
- free,
- NULL,
- &untracked_calloc_allocator);
+ enabled = true;
pthread_mutex_unlock(&lock);
}
// Test function only. Do not call in the normal course of operations.
void allocation_tracker_uninit(void) {
- if (!allocations)
+ if (!enabled)
return;
pthread_mutex_lock(&lock);
- hash_map_free(allocations);
- allocations = NULL;
+ allocations.clear();
+ enabled = false;
pthread_mutex_unlock(&lock);
}
void allocation_tracker_reset(void) {
- if (!allocations)
+ if (!enabled)
return;
pthread_mutex_lock(&lock);
- hash_map_clear(allocations);
+ allocations.clear();
pthread_mutex_unlock(&lock);
}
size_t allocation_tracker_expect_no_allocations(void) {
- if (!allocations)
+ if (!enabled)
return 0;
pthread_mutex_lock(&lock);
size_t unfreed_memory_size = 0;
- hash_map_foreach(allocations, allocation_entry_freed_checker, &unfreed_memory_size);
+
+ for (const auto &entry : allocations) {
+ allocation_t *allocation = entry.second;
+ if (!allocation->freed) {
+ unfreed_memory_size += allocation->size; // Report back the unfreed byte count
+ LOG_ERROR(LOG_TAG, "%s found unfreed allocation. address: 0x%zx size: %zd bytes", __func__, (uintptr_t)allocation->ptr, allocation->size);
+ }
+ }
pthread_mutex_unlock(&lock);
@@ -116,7 +96,7 @@
}
void *allocation_tracker_notify_alloc(uint8_t allocator_id, void *ptr, size_t requested_size) {
- if (!allocations || !ptr)
+ if (!enabled || !ptr)
return ptr;
char *return_ptr = (char *)ptr;
@@ -125,12 +105,14 @@
pthread_mutex_lock(&lock);
- allocation_t *allocation = (allocation_t *)hash_map_get(allocations, return_ptr);
- if (allocation) {
+ auto map_entry = allocations.find(return_ptr);
+ allocation_t *allocation;
+ if (map_entry != allocations.end()) {
+ allocation = map_entry->second;
assert(allocation->freed); // Must have been freed before
} else {
allocation = (allocation_t *)calloc(1, sizeof(allocation_t));
- hash_map_set(allocations, return_ptr, allocation);
+ allocations[return_ptr] = allocation;
}
allocation->allocator_id = allocator_id;
@@ -148,12 +130,14 @@
}
void *allocation_tracker_notify_free(UNUSED_ATTR uint8_t allocator_id, void *ptr) {
- if (!allocations || !ptr)
+ if (!enabled || !ptr)
return ptr;
pthread_mutex_lock(&lock);
- allocation_t *allocation = (allocation_t *)hash_map_get(allocations, ptr);
+ auto map_entry = allocations.find(ptr);
+ assert(map_entry != allocations.end());
+ allocation_t *allocation = map_entry->second;
assert(allocation); // Must have been tracked before
assert(!allocation->freed); // Must not be a double free
assert(allocation->allocator_id == allocator_id); // Must be from the same allocator
@@ -170,7 +154,7 @@
// Free the hash map entry to avoid unlimited memory usage growth.
// Double-free of memory is detected with "assert(allocation)" above
// as the allocation entry will not be present.
- hash_map_erase(allocations, ptr);
+ allocations.erase(ptr);
pthread_mutex_unlock(&lock);
@@ -178,19 +162,5 @@
}
size_t allocation_tracker_resize_for_canary(size_t size) {
- return (!allocations) ? size : size + (2 * canary_size);
-}
-
-static bool allocation_entry_freed_checker(hash_map_entry_t *entry, void *context) {
- allocation_t *allocation = (allocation_t *)entry->data;
- if (!allocation->freed) {
- *((size_t *)context) += allocation->size; // Report back the unfreed byte count
- LOG_ERROR(LOG_TAG, "%s found unfreed allocation. address: 0x%zx size: %zd bytes", __func__, (uintptr_t)allocation->ptr, allocation->size);
- }
-
- return true;
-}
-
-static void *untracked_calloc(size_t size) {
- return calloc(size, 1);
+ return (!enabled) ? size : size + (2 * canary_size);
}
diff --git a/osi/test/allocation_tracker_test.cc b/osi/test/allocation_tracker_test.cc
index ab5f61f..ac2f6fb 100644
--- a/osi/test/allocation_tracker_test.cc
+++ b/osi/test/allocation_tracker_test.cc
@@ -20,9 +20,9 @@
extern "C" {
#include "osi/include/allocation_tracker.h"
+}
void allocation_tracker_uninit(void);
-}
static const allocator_id_t allocator_id = 5;