Skip to content

Commit 0d0c5a9

Browse files
committed
Fix memory leak of obmalloc state.
Free the obmalloc arenas, radix tree nodes and allarenas array when the interpreter state is freed.
1 parent f5c05e0 commit 0d0c5a9

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

Objects/obmalloc.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,8 @@ _PyInterpreterState_GetAllocatedBlocks(PyInterpreterState *interp)
10521052
return n;
10531053
}
10541054

1055+
static void free_arenas(PyInterpreterState *interp);
1056+
10551057
void
10561058
_PyInterpreterState_FinalizeAllocatedBlocks(PyInterpreterState *interp)
10571059
{
@@ -1065,6 +1067,7 @@ _PyInterpreterState_FinalizeAllocatedBlocks(PyInterpreterState *interp)
10651067
assert(has_own_state(interp) || leaked == 0);
10661068
interp->runtime->obmalloc.interpreter_leaks += leaked;
10671069
}
1070+
free_arenas(interp);
10681071
}
10691072

10701073
static Py_ssize_t get_num_global_allocated_blocks(_PyRuntimeState *);
@@ -2612,6 +2615,37 @@ _PyObject_DebugDumpAddress(const void *p)
26122615
_PyMem_DumpTraceback(fileno(stderr), p);
26132616
}
26142617

2618+
static void
2619+
free_arenas(PyInterpreterState *interp)
2620+
{
2621+
OMState *state = &interp->obmalloc;
2622+
for (uint i = 0; i < maxarenas; ++i) {
2623+
// free each obmalloc memory arena
2624+
struct arena_object *ao = &allarenas[i];
2625+
_PyObject_Arena.free(_PyObject_Arena.ctx,
2626+
(void *)ao->address, ARENA_SIZE);
2627+
}
2628+
// free the array containing pointers to all arenas
2629+
PyMem_RawFree(allarenas);
2630+
#if WITH_PYMALLOC_RADIX_TREE
2631+
// Free the middle and bottom nodes of the radix tree. These are allocated
2632+
// by arena_map_mark_used() but not freed when arenas are freed.
2633+
for (int i1 = 0; i1 < MAP_TOP_LENGTH; i1++) {
2634+
arena_map_mid_t *mid = arena_map_root.ptrs[i1];
2635+
if (mid == NULL) {
2636+
continue;
2637+
}
2638+
for (int i2 = 0; i2 < MAP_MID_LENGTH; i2++) {
2639+
arena_map_bot_t *bot = arena_map_root.ptrs[i1]->ptrs[i2];
2640+
if (bot == NULL) {
2641+
continue;
2642+
}
2643+
PyMem_RawFree(bot);
2644+
}
2645+
PyMem_RawFree(mid);
2646+
}
2647+
#endif
2648+
}
26152649

26162650
static size_t
26172651
printone(FILE *out, const char* msg, size_t value)

0 commit comments

Comments
 (0)