From cfd3bcb21eeec8b81ea41f706b6bdb87ac034b1a Mon Sep 17 00:00:00 2001 From: Christian McDonald Date: Fri, 13 Jan 2023 16:39:28 -0500 Subject: [PATCH 1/5] eliminate unnecessary Python reloading which causes memory leaks --- pythonmod/pythonmod.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c index 28ce0eec4..19b464633 100644 --- a/pythonmod/pythonmod.c +++ b/pythonmod/pythonmod.c @@ -252,6 +252,16 @@ cleanup: Py_XDECREF(exc_tb); } +/* we only want to unwind Python once at exit */ +void pythonmod_atexit(void) +{ + assert(py_mod_count == 0); + assert(maimthr != NULL); + + PyEval_RestoreThread(mainthr); + Py_Finalize(); +} + int pythonmod_init(struct module_env* env, int id) { int py_mod_idx = py_mod_count++; @@ -310,6 +320,9 @@ int pythonmod_init(struct module_env* env, int id) #endif SWIG_init(); mainthr = PyEval_SaveThread(); + + /* XXX: register callback to unwind Python at exit */ + atexit(pythonmod_atexit); } gil = PyGILState_Ensure(); @@ -547,11 +560,7 @@ void pythonmod_deinit(struct module_env* env, int id) Py_XDECREF(pe->data); PyGILState_Release(gil); - if(--py_mod_count==0) { - PyEval_RestoreThread(mainthr); - Py_Finalize(); - mainthr = NULL; - } + py_mod_count--; } pe->fname = NULL; free(pe); From 55a28d69466e460c71ab6d1627cf540e98e912a9 Mon Sep 17 00:00:00 2001 From: "R. Christian McDonald" Date: Thu, 19 Jan 2023 16:30:47 -0500 Subject: [PATCH 2/5] cleanup callbacks that might have been registered by Python script --- pythonmod/pythonmod.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c index 19b464633..aa8609c58 100644 --- a/pythonmod/pythonmod.c +++ b/pythonmod/pythonmod.c @@ -3,6 +3,7 @@ * * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + * Copyright (c) 2022, Rubicon Communications, LLC (Netgate) * * This software is open source. * @@ -567,6 +568,10 @@ void pythonmod_deinit(struct module_env* env, int id) /* Module is deallocated in Python */ env->modinfo[id] = NULL; + + /* iterate over all possible callback types and clean up each in turn */ + for (int cbtype = 0; cbtype < inplace_cb_types_total; cbtype++) + inplace_cb_delete(env, cbtype, id); } void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super) From 45142868ecba8823d8c6f69c34502e80f628445d Mon Sep 17 00:00:00 2001 From: "R. Christian McDonald" Date: Sat, 28 Jan 2023 14:02:51 -0500 Subject: [PATCH 3/5] Fix copyright date --- pythonmod/pythonmod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c index aa8609c58..74a5d6607 100644 --- a/pythonmod/pythonmod.c +++ b/pythonmod/pythonmod.c @@ -3,7 +3,7 @@ * * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - * Copyright (c) 2022, Rubicon Communications, LLC (Netgate) + * Copyright (c) 2023, Rubicon Communications, LLC (Netgate) * * This software is open source. * From 0bf55e60636d3172a9280703f93faab62d8a997a Mon Sep 17 00:00:00 2001 From: Christian McDonald Date: Wed, 1 Feb 2023 15:17:59 -0500 Subject: [PATCH 4/5] set modinfo to null last --- pythonmod/pythonmod.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c index 74a5d6607..d4042995e 100644 --- a/pythonmod/pythonmod.c +++ b/pythonmod/pythonmod.c @@ -566,12 +566,12 @@ void pythonmod_deinit(struct module_env* env, int id) pe->fname = NULL; free(pe); - /* Module is deallocated in Python */ - env->modinfo[id] = NULL; - /* iterate over all possible callback types and clean up each in turn */ for (int cbtype = 0; cbtype < inplace_cb_types_total; cbtype++) inplace_cb_delete(env, cbtype, id); + + /* Module is deallocated in Python */ + env->modinfo[id] = NULL; } void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super) From 60304f972ed29b420618070b1f62413f8fe1fd65 Mon Sep 17 00:00:00 2001 From: Christian McDonald Date: Fri, 24 Feb 2023 09:31:19 -0500 Subject: [PATCH 5/5] #827 review response --- pythonmod/pythonmod.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c index d4042995e..6d8539bd5 100644 --- a/pythonmod/pythonmod.c +++ b/pythonmod/pythonmod.c @@ -3,7 +3,6 @@ * * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - * Copyright (c) 2023, Rubicon Communications, LLC (Netgate) * * This software is open source. * @@ -254,10 +253,11 @@ cleanup: } /* we only want to unwind Python once at exit */ -void pythonmod_atexit(void) +static void +pythonmod_atexit(void) { - assert(py_mod_count == 0); - assert(maimthr != NULL); + log_assert(py_mod_count == 0); + log_assert(mainthr != NULL); PyEval_RestoreThread(mainthr); Py_Finalize(); @@ -322,7 +322,7 @@ int pythonmod_init(struct module_env* env, int id) SWIG_init(); mainthr = PyEval_SaveThread(); - /* XXX: register callback to unwind Python at exit */ + /* register callback to unwind Python at exit */ atexit(pythonmod_atexit); } @@ -539,6 +539,7 @@ python_init_fail: void pythonmod_deinit(struct module_env* env, int id) { + int cbtype; struct pythonmod_env* pe = env->modinfo[id]; if(pe == NULL) return; @@ -567,7 +568,7 @@ void pythonmod_deinit(struct module_env* env, int id) free(pe); /* iterate over all possible callback types and clean up each in turn */ - for (int cbtype = 0; cbtype < inplace_cb_types_total; cbtype++) + for (cbtype = 0; cbtype < inplace_cb_types_total; cbtype++) inplace_cb_delete(env, cbtype, id); /* Module is deallocated in Python */