[gnumeric] PythonLoader: plug leaks.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] PythonLoader: plug leaks.
- Date: Sun, 21 Mar 2021 22:46:53 +0000 (UTC)
commit 5d1d129ecc2eec58a2bb7f530e7a97e71b240c30
Author: Morten Welinder <terra gnome org>
Date: Sun Mar 21 18:46:17 2021 -0400
PythonLoader: plug leaks.
There are more, but it's hard to see if we or python are to blame.
plugins/python-loader/ChangeLog | 3 +++
plugins/python-loader/boot.c | 7 +++++
plugins/python-loader/gnm-py-interpreter.c | 21 ++++++++++-----
plugins/python-loader/gnm-python.c | 1 +
plugins/python-loader/py-gnumeric.c | 42 +++++++++++++++++++++++-------
plugins/python-loader/py-gnumeric.h | 4 ++-
plugins/python-loader/python-loader.c | 10 ++++---
7 files changed, 69 insertions(+), 19 deletions(-)
---
diff --git a/plugins/python-loader/ChangeLog b/plugins/python-loader/ChangeLog
index 3154a10d5..abbe18227 100644
--- a/plugins/python-loader/ChangeLog
+++ b/plugins/python-loader/ChangeLog
@@ -1,5 +1,8 @@
2021-03-21 Morten Welinder <terra gnome org>
+ * py-gnumeric.c (py_obj_to_gnm_value): Handle python ints via
+ gnm_float, not int, so we handle larger numbers.
+
* python-loader.c (gplp_unload_service_function_group): Clear
python_fn_info_dict after unref so we don't do it again.
(python_function_get_gnumeric_help): Check for tuple before using.
diff --git a/plugins/python-loader/boot.c b/plugins/python-loader/boot.c
index 788f2bbac..4f1d84ad2 100644
--- a/plugins/python-loader/boot.c
+++ b/plugins/python-loader/boot.c
@@ -9,6 +9,7 @@
#include "gnm-py-interpreter.h"
#include "python-loader.h"
#include "py-console.h"
+#include <py-gnumeric.h>
#include <gnm-plugin.h>
#include <goffice/goffice.h>
#include <gnm-plugin.h>
@@ -39,3 +40,9 @@ go_plugin_init (GOPlugin *plugin, GOCmdContext *cc)
gnm_py_interpreter_selector_register_type (module);
gnm_python_plugin_loader_register_type (module);
}
+
+G_MODULE_EXPORT void
+go_plugin_shutdown (GOPlugin *plugin, GOCmdContext *cc)
+{
+ py_gnumeric_shutdown ();
+}
diff --git a/plugins/python-loader/gnm-py-interpreter.c b/plugins/python-loader/gnm-py-interpreter.c
index 444a8d125..b0540cf2c 100644
--- a/plugins/python-loader/gnm-py-interpreter.c
+++ b/plugins/python-loader/gnm-py-interpreter.c
@@ -17,6 +17,14 @@
#include <gsf/gsf-impl-utils.h>
#include <glib/gi18n-lib.h>
+// Like PyDict_SetItemString, but takes ownership of val
+static void
+gnm_py_dict_store (PyObject *dict, const char *key, PyObject *val)
+{
+ PyDict_SetItemString (dict, key, val);
+ Py_DECREF (val);
+}
+
struct _GnmPyInterpreter {
GObject parent_instance;
@@ -100,8 +108,9 @@ gnm_py_interpreter_new (GOPlugin *plugin)
interpreter->plugin = plugin;
PySys_SetArgv (G_N_ELEMENTS (plugin_argv) - 1, plugin_argv);
- if (plugin != NULL)
+ if (plugin != NULL) {
py_gnumeric_add_plugin (py_initgnumeric (), interpreter);
+ }
return interpreter;
}
@@ -196,7 +205,7 @@ gnm_py_interpreter_run_string (GnmPyInterpreter *interpreter, const char *cmd,
}
if (opt_stdout != NULL) {
stdout_obj = PyType_GenericNew(interpreter->stringio_class,
- NULL, NULL);
+ NULL, NULL);
if (stdout_obj == NULL)
PyErr_Print ();
g_return_if_fail (stdout_obj != NULL);
@@ -205,7 +214,7 @@ gnm_py_interpreter_run_string (GnmPyInterpreter *interpreter, const char *cmd,
"stdout");
g_return_if_fail (saved_stdout_obj != NULL);
Py_INCREF (saved_stdout_obj);
- PyDict_SetItemString (sys_module_dict, "stdout",
+ gnm_py_dict_store (sys_module_dict, "stdout",
stdout_obj);
}
if (opt_stderr != NULL) {
@@ -219,12 +228,12 @@ gnm_py_interpreter_run_string (GnmPyInterpreter *interpreter, const char *cmd,
"stderr");
g_return_if_fail (saved_stderr_obj != NULL);
Py_INCREF (saved_stderr_obj);
- PyDict_SetItemString (sys_module_dict, "stderr",
+ gnm_py_dict_store (sys_module_dict, "stderr",
stderr_obj);
}
run_print_string (cmd, stdout_obj);
if (opt_stdout != NULL) {
- PyDict_SetItemString (sys_module_dict, "stdout",
+ gnm_py_dict_store (sys_module_dict, "stdout",
saved_stdout_obj);
Py_DECREF (saved_stdout_obj);
py_str = PyObject_CallMethod (stdout_obj, "getvalue",
@@ -238,7 +247,7 @@ gnm_py_interpreter_run_string (GnmPyInterpreter *interpreter, const char *cmd,
Py_DECREF (stdout_obj);
}
if (opt_stderr != NULL) {
- PyDict_SetItemString (sys_module_dict, "stderr",
+ gnm_py_dict_store (sys_module_dict, "stderr",
saved_stderr_obj);
Py_DECREF (saved_stderr_obj);
py_str = PyObject_CallMethod (stderr_obj, "getvalue",
diff --git a/plugins/python-loader/gnm-python.c b/plugins/python-loader/gnm-python.c
index 4bc517352..7e4a2b281 100644
--- a/plugins/python-loader/gnm-python.c
+++ b/plugins/python-loader/gnm-python.c
@@ -79,6 +79,7 @@ gnm_python_finalize (GObject *obj)
);
g_slist_free (ints);
gnm_py_interpreter_switch_to (gpy->default_interpreter);
+ GO_SLIST_REMOVE (gpy->interpreters, gpy->default_interpreter);
g_object_unref (gpy->default_interpreter);
gpy->default_interpreter = NULL;
}
diff --git a/plugins/python-loader/py-gnumeric.c b/plugins/python-loader/py-gnumeric.c
index 826d9d6bf..14e04eca8 100644
--- a/plugins/python-loader/py-gnumeric.c
+++ b/plugins/python-loader/py-gnumeric.c
@@ -78,12 +78,25 @@ Module Gnumeric:
*/
+
+// Like PyDict_SetItemString, but takes ownership of val
+static void
+gnm_py_dict_store (PyObject *dict, const char *key, PyObject *val)
+{
+ PyDict_SetItemString (dict, key, val);
+ Py_DECREF (val);
+}
+
+
+
+
+
#define GNUMERIC_MODULE \
(PyImport_AddModule ("Gnumeric"))
#define GNUMERIC_MODULE_GET(key) \
PyDict_GetItemString (PyModule_GetDict (GNUMERIC_MODULE), (key))
#define GNUMERIC_MODULE_SET(key, val) \
- PyDict_SetItemString (PyModule_GetDict (GNUMERIC_MODULE), (key), val)
+ gnm_py_dict_store (PyModule_GetDict (GNUMERIC_MODULE), (key), val)
#define SET_EVAL_POS(val) \
GNUMERIC_MODULE_SET ("Gnumeric_eval_pos", PyCapsule_New (val, "eval_pos", NULL))
#define UNSET_EVAL_POS \
@@ -107,7 +120,7 @@ py_obj_to_gnm_value (const GnmEvalPos *eval_pos, PyObject *py_val)
} else if (py_val_type == (PyObject *) &py_Boolean_object_type) {
ret_val = value_new_bool (py_Boolean_as_gboolean ((py_Boolean_object *) py_val));
} else if (PyLong_Check (py_val)) {
- ret_val = value_new_int ((gint) PyLong_AsLong (py_val));
+ ret_val = value_new_float ((gnm_float)PyLong_AsLong (py_val));
} else if (PyFloat_Check (py_val)) {
ret_val = value_new_float ((gnm_float) PyFloat_AsDouble (py_val));
} else if (PyUnicode_Check (py_val)) {
@@ -832,7 +845,7 @@ init_err (PyObject *module_dict, const char *name, GnmStdError e)
{
GnmValue *v = value_new_error_std (NULL, e);
- PyDict_SetItemString
+ gnm_py_dict_store
(module_dict, name,
PyUnicode_FromString (v->v_err.mesg->str));
@@ -841,7 +854,7 @@ init_err (PyObject *module_dict, const char *name, GnmStdError e)
PyObject *
-py_initgnumeric ()
+py_initgnumeric (void)
{
PyObject *module_dict;
@@ -862,12 +875,12 @@ py_initgnumeric ()
GnmModule = PyModule_Create (&GnmModuleDef);
module_dict = PyModule_GetDict (GnmModule);
- (void) PyDict_SetItemString
+ gnm_py_dict_store
(module_dict, "TRUE", py_new_Boolean_object (TRUE));
- (void) PyDict_SetItemString
+ gnm_py_dict_store
(module_dict, "FALSE", py_new_Boolean_object (FALSE));
- (void) PyDict_SetItemString
+ gnm_py_dict_store
(module_dict, "GnumericError",
PyErr_NewException ("Gnumeric.GnumericError",
NULL, NULL));
@@ -880,13 +893,24 @@ py_initgnumeric ()
init_err (module_dict, "GnumericErrorNUM", GNM_ERROR_NUM);
init_err (module_dict, "GnumericErrorNA", GNM_ERROR_NA);
- (void) PyDict_SetItemString
+ gnm_py_dict_store
(module_dict, "functions",
py_new_GnumericFuncDict_object (module_dict));
return GnmModule;
}
+void
+py_gnumeric_shutdown (void)
+{
+ if (GnmModule) {
+ // At least clear the module. We leak a ref somewhere.
+ PyDict_Clear (PyModule_GetDict (GnmModule));
+ Py_DECREF (GnmModule);
+ GnmModule = NULL;
+ }
+}
+
void
py_gnumeric_add_plugin (PyObject *module, GnmPyInterpreter *interpreter)
{
@@ -905,7 +929,7 @@ py_gnumeric_add_plugin (PyObject *module, GnmPyInterpreter *interpreter)
name[i] = '_';
key = g_strconcat ("plugin_", name, "_info", NULL);
py_pinfo = py_new_GnmPlugin_object (pinfo);
- (void) PyDict_SetItemString (module_dict, key, py_pinfo);
+ gnm_py_dict_store (module_dict, key, py_pinfo);
g_free (name);
g_free (key);
}
diff --git a/plugins/python-loader/py-gnumeric.h b/plugins/python-loader/py-gnumeric.h
index 9ea35919f..9a68d647f 100644
--- a/plugins/python-loader/py-gnumeric.h
+++ b/plugins/python-loader/py-gnumeric.h
@@ -8,10 +8,12 @@
#include <gnumeric-fwd.h>
PyObject *py_initgnumeric (void);
+void py_gnumeric_shutdown (void);
+
void py_gnumeric_add_plugin (PyObject *module, GnmPyInterpreter *interpreter);
GnmValue *call_python_function (PyObject *python_fn,
GnmEvalPos const *eval_pos,
gint n_args, GnmValue const * const *args);
gchar *py_exc_to_string (void);
-#endif /* PLUGIN_PY_GNUMERIC_H */
\ No newline at end of file
+#endif /* PLUGIN_PY_GNUMERIC_H */
diff --git a/plugins/python-loader/python-loader.c b/plugins/python-loader/python-loader.c
index 2e6616d53..1ca96287f 100644
--- a/plugins/python-loader/python-loader.c
+++ b/plugins/python-loader/python-loader.c
@@ -547,6 +547,7 @@ python_function_get_gnumeric_help (PyObject *python_fn_info_dict, PyObject *pyth
PyObject *cobject_help_value;
PyObject *python_arg_names;
PyObject *fn_info_obj;
+ GnmFuncHelp const *res = NULL;
fn_info_obj = PyDict_GetItemString (python_fn_info_dict, fn_name);
python_arg_names = PyTuple_Check (fn_info_obj)
@@ -657,10 +658,13 @@ python_function_get_gnumeric_help (PyObject *python_fn_info_dict, PyObject *pyth
}
}
g_free (help_attr_name);
- if (cobject_help_value == NULL)
- return NULL;
- return (GnmFuncHelp const *) PyCapsule_GetPointer (cobject_help_value, "FuncHelp");
+ if (cobject_help_value) {
+ res = (GnmFuncHelp const *) PyCapsule_GetPointer (cobject_help_value, "FuncHelp");
+ Py_DECREF (cobject_help_value);
+ }
+
+ return res;
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]