diff options
author | Paul Pogonyshev <pogonyshev@gmx.net> | 2009-04-13 20:28:24 +0000 |
---|---|---|
committer | Paul Pogonyshev <paulp@src.gnome.org> | 2009-04-13 20:28:24 +0000 |
commit | 9f5ce31f7f42dc8d3d6062cb17c87fb57b23817a (patch) | |
tree | c3daddbd3d6fe18c99dd0898fc864f2a2b0c53f0 /gio | |
parent | 37938b14a08f00b36aa575c2e9a74cf15d425ccf (diff) | |
download | pygobject-9f5ce31f7f42dc8d3d6062cb17c87fb57b23817a.tar.gz pygobject-9f5ce31f7f42dc8d3d6062cb17c87fb57b23817a.tar.xz pygobject-9f5ce31f7f42dc8d3d6062cb17c87fb57b23817a.zip |
Bug 578870 – memory leak in gio.File.copy_async
2009-04-13 Paul Pogonyshev <pogonyshev@gmx.net>
Bug 578870 – memory leak in gio.File.copy_async
* gio/gio.override (PyGIONotify): Add 'slaves' field.
(pygio_notify_new_slave): New function.
(pygio_notify_reference_callback): Recurse for slaves, if any.
(pygio_notify_free): Likewise.
* gio/gfile.override (file_progress_callback_marshal): Use new
chaining functionality to avoid leaking the second PyGIONotify
structure. Rename 'callback' as 'progress_callback' for clarity.
svn path=/trunk/; revision=1060
Diffstat (limited to 'gio')
-rw-r--r-- | gio/gfile.override | 13 | ||||
-rw-r--r-- | gio/gio.override | 28 |
2 files changed, 32 insertions, 9 deletions
diff --git a/gio/gfile.override b/gio/gfile.override index 4cbeb1c..99c6395 100644 --- a/gio/gfile.override +++ b/gio/gfile.override @@ -601,10 +601,12 @@ _wrap_g_file_copy_async(PyGObject *self, int io_priority = G_PRIORITY_DEFAULT; PyGObject *pycancellable = NULL; GCancellable *cancellable; - GFileProgressCallback callback = NULL; + GFileProgressCallback progress_callback = NULL; + /* After the creation, referencing/freeing will automatically be + * done on the master and the slave. */ notify = pygio_notify_new(); - progress_notify = pygio_notify_new(); + progress_notify = pygio_notify_new_slave(notify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O|OiOOOO:File.copy_async", @@ -627,7 +629,7 @@ _wrap_g_file_copy_async(PyGObject *self, goto error; if (pygio_notify_using_optional_callback(progress_notify)) { - callback = (GFileProgressCallback)file_progress_callback_marshal; + progress_callback = (GFileProgressCallback) file_progress_callback_marshal; if (!pygio_notify_callback_is_valid_full(progress_notify, "progress_callback")) goto error; } @@ -636,15 +638,13 @@ _wrap_g_file_copy_async(PyGObject *self, goto error; pygio_notify_reference_callback(notify); - pygio_notify_reference_callback(progress_notify); - /* FIXME: 'progress_notify' is not properly freed up as far as I see. */ g_file_copy_async(G_FILE(self->obj), G_FILE(destination->obj), flags, io_priority, cancellable, - callback, + progress_callback, progress_notify, (GAsyncReadyCallback)async_result_callback_marshal, notify); @@ -654,7 +654,6 @@ _wrap_g_file_copy_async(PyGObject *self, error: pygio_notify_free(notify); - pygio_notify_free(progress_notify); return NULL; } %% diff --git a/gio/gio.override b/gio/gio.override index 5170624..0d5da96 100644 --- a/gio/gio.override +++ b/gio/gio.override @@ -33,14 +33,20 @@ headers #define BUFSIZE 8192 -typedef struct { +typedef struct _PyGIONotify PyGIONotify; + +struct _PyGIONotify { gboolean referenced; PyObject *callback; PyObject *data; gboolean attach_self; gpointer buffer; gsize buffer_size; -} PyGIONotify; + + /* If a structure has any 'slaves', those will reference their + * callbacks and be freed together with the 'master'. */ + PyGIONotify *slaves; +}; static GQuark pygio_notify_get_internal_quark(void) @@ -57,6 +63,18 @@ pygio_notify_new(void) return g_slice_new0(PyGIONotify); } +static PyGIONotify * +pygio_notify_new_slave(PyGIONotify* master) +{ + PyGIONotify *slave = pygio_notify_new(); + + while (master->slaves) + master = master->slaves; + master->slaves = slave; + + return slave; +} + static gboolean pygio_notify_using_optional_callback(PyGIONotify *notify) { @@ -100,6 +118,9 @@ pygio_notify_reference_callback(PyGIONotify *notify) notify->referenced = TRUE; Py_XINCREF(notify->callback); Py_XINCREF(notify->data); + + if (notify->slaves) + pygio_notify_reference_callback(notify->slaves); } } @@ -144,6 +165,9 @@ static void pygio_notify_free(PyGIONotify *notify) { if (notify) { + if (notify->slaves) + pygio_notify_free(notify->slaves); + if (notify->referenced) { PyGILState_STATE state; |