Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed memory leaks #895

Merged
merged 6 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,8 @@ if(MEMORYCHECK_COMMAND)
add_custom_command(
OUTPUT ${logfile}
COMMAND ${CMAKE_COMMAND}
-E env PYTHONMALLOC=malloc ${MEMORYCHECK_COMMAND}
-E env PYTHONMALLOC=malloc DLITE_ATEXIT_FREE=
-- ${MEMORYCHECK_COMMAND}
--leak-check=yes
--show-leak-kinds=all
--keep-debuginfo=yes
Expand Down
23 changes: 23 additions & 0 deletions cmake/valgrind-python.supp
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,29 @@
fun:Py_BytesMain
}

{
Leak in numpy random_bit_generator (py311, alvis)
Memcheck:Leak
match-leak-kinds: definite
fun:calloc
obj:/usr/lib64/libgomp.so.1.0.0
obj:/usr/lib64/libgomp.so.1.0.0
obj:/usr/lib64/libgomp.so.1.0.0
fun:call_init
fun:call_init
fun:_dl_init
fun:_dl_catch_exception
}

{
Leak in pydantic initialisation (py311)
Memcheck:Leak
match-leak-kinds: definite
fun:realloc
...
fun:PyInit__pydantic_core
}


# ------------------------------------
# Python plugins
Expand Down
8 changes: 8 additions & 0 deletions src/dlite-mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ DLiteMapping *mapping_create_rec(const char *output_uri, Instances *inputs,
}
if (ignore) continue;

/*
FIXME: avoid memory leak
Implement dlite_mapping_plugin_free() and call it here.

Even better, implement caching in dlite_mapping_plugin_next()
such that it returns borrowed references to the api. Add a function
to clear the cache.
*/
if (!cheapest || cost < lowest_cost) {
cheapest = api;
lowest_cost = cost;
Expand Down
8 changes: 7 additions & 1 deletion src/dlite-misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ int dlite_add_dll_path(void)
/* Local state for this module. */
typedef struct {
int in_atexit;
int finalizing;
} Locals;


Expand Down Expand Up @@ -496,7 +497,7 @@ static Locals *get_locals(void)
static void _handle_atexit(void) {

/* No extra finalisation is needed if we already are in an atexit handler */
if (dlite_globals_in_atexit()) return;
if (dlite_globals_in_atexit() && !getenv("DLITE_ATEXIT_FREE")) return;

/* Mark that we are in an atexit handler */
dlite_globals_set_atexit();
Expand Down Expand Up @@ -582,6 +583,11 @@ void dlite_init(void)
void dlite_finalize(void)
{
Session *s = session_get_default();
Locals *locals = get_locals();

/* Ensure that we only finalize once. */
if (locals->finalizing) return;
locals->finalizing = 1;

/* Don't free anything if we are in an atexit handler */
if (dlite_globals_in_atexit() && !getenv("DLITE_ATEXIT_FREE")) return;
Expand Down
2 changes: 1 addition & 1 deletion src/pyembed/dlite-python-storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static void free_globals(void *globals)
if (g->initialised) fu_paths_deinit(&g->paths);

/* Do not call Py_DECREF if we are in an atexit handler */
if (!dlite_globals_in_atexit() || getenv("DLITE_ATEXIT_FREE")) {
if (!dlite_globals_in_atexit()) {
Py_XDECREF(g->loaded_storages);
g->loaded_storages = NULL;
}
Expand Down
5 changes: 4 additions & 1 deletion storages/json/dlite-json-storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,12 @@ DLiteInstance *json_memload(const DLiteStoragePlugin *api,
const unsigned char *buf, size_t size,
const char *id, const char *options)
{
DLiteInstance *inst;
DLiteStorage *s = json_loader(api, NULL, buf, size, options);
DLiteInstance *inst = json_load(s, id);
if (!s) return NULL;
inst = json_load(s, id);
json_close(s);
free(s);
return inst;
}

Expand Down