[gnumeric] PythonLoader: plug leaks.



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]