[evolution-data-server/gnome-2-32] Bug #627788 - EDataCalView is never freed in a factory process (cherry picked from commit a65b1d9441
- From: David Woodhouse <dwmw2 src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/gnome-2-32] Bug #627788 - EDataCalView is never freed in a factory process (cherry picked from commit a65b1d9441
- Date: Wed, 11 May 2011 00:45:14 +0000 (UTC)
commit 00ecef7054c38e423acde619df71c68e6355edbc
Author: Milan Crha <mcrha redhat com>
Date: Thu Jan 13 18:46:16 2011 +0100
Bug #627788 - EDataCalView is never freed in a factory process
(cherry picked from commit a65b1d94415326418dd9663cbae041abc51f4a47)
addressbook/tests/ebook/test-stress-bookviews.c | 1 +
calendar/libecal/e-cal-view.c | 15 ++-
calendar/libedata-cal/e-cal-backend.c | 22 +--
calendar/libedata-cal/e-data-cal-factory.c | 11 ++
calendar/libedata-cal/e-data-cal-view.c | 12 ++
calendar/libedata-cal/e-data-cal-view.xml | 4 +
calendar/libegdbus/e-gdbus-egdbuscalview.c | 169 +++++++++++++++++++++++
calendar/libegdbus/e-gdbus-egdbuscalview.h | 24 ++++
8 files changed, 239 insertions(+), 19 deletions(-)
---
diff --git a/addressbook/tests/ebook/test-stress-bookviews.c b/addressbook/tests/ebook/test-stress-bookviews.c
index 4f6e871..d7522fe 100644
--- a/addressbook/tests/ebook/test-stress-bookviews.c
+++ b/addressbook/tests/ebook/test-stress-bookviews.c
@@ -100,6 +100,7 @@ main (gint argc, gchar **argv)
g_object_unref (view);
e_book_query_unref (query);
+ g_object_unref (book);
return 0;
}
diff --git a/calendar/libecal/e-cal-view.c b/calendar/libecal/e-cal-view.c
index a21943c..af132ca 100644
--- a/calendar/libecal/e-cal-view.c
+++ b/calendar/libecal/e-cal-view.c
@@ -193,10 +193,8 @@ e_cal_view_set_property (GObject *object, guint property_id, const GValue *value
switch (property_id) {
case PROP_VIEW:
- if (priv->gdbus_calview != NULL) {
- g_signal_handlers_disconnect_matched (priv->gdbus_calview, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view);
- g_object_unref (priv->gdbus_calview);
- }
+ /* gdbus_calview can be set only once */
+ g_return_if_fail (priv->gdbus_calview == NULL);
priv->gdbus_calview = g_object_ref (g_value_get_pointer (value));
g_signal_connect (priv->gdbus_calview, "objects-added", G_CALLBACK (objects_added_cb), view);
@@ -250,8 +248,17 @@ e_cal_view_finalize (GObject *object)
priv = view->priv;
if (priv->gdbus_calview != NULL) {
+ GError *error = NULL;
+
g_signal_handlers_disconnect_matched (priv->gdbus_calview, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view);
+ e_gdbus_cal_view_call_dispose_sync (priv->gdbus_calview, NULL, &error);
g_object_unref (priv->gdbus_calview);
+ priv->gdbus_calview = NULL;
+
+ if (error) {
+ g_warning ("Failed to dispose cal view: %s", error->message);
+ g_error_free (error);
+ }
}
g_object_unref (priv->client);
diff --git a/calendar/libedata-cal/e-cal-backend.c b/calendar/libedata-cal/e-cal-backend.c
index eb2cc0f..f654c24 100644
--- a/calendar/libedata-cal/e-cal-backend.c
+++ b/calendar/libedata-cal/e-cal-backend.c
@@ -44,8 +44,6 @@
struct _ECalBackendPrivate {
/* The source for this backend */
ESource *source;
- /* signal handler ID for source's 'changed' signal */
- gulong source_changed_id;
/* URI, from source. This is cached, since we return const. */
gchar *uri;
@@ -161,17 +159,12 @@ cal_backend_set_source (ECalBackend *backend,
ESource *source)
{
if (backend->priv->source != NULL) {
- if (backend->priv->source_changed_id > 0) {
- g_signal_handler_disconnect (
- backend->priv->source,
- backend->priv->source_changed_id);
- backend->priv->source_changed_id = 0;
- }
+ g_signal_handlers_disconnect_matched (backend->priv->source, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, source_changed_cb, backend);
g_object_unref (backend->priv->source);
}
if (source != NULL)
- backend->priv->source_changed_id = g_signal_connect (
+ g_signal_connect (
g_object_ref (source), "changed",
G_CALLBACK (source_changed_cb), backend);
@@ -283,11 +276,10 @@ cal_backend_finalize (GObject *object)
g_free (priv->uri);
g_free (priv->cache_dir);
- if (priv->source_changed_id && priv->source) {
- g_signal_handler_disconnect (priv->source, priv->source_changed_id);
- priv->source_changed_id = 0;
+ if (priv->source) {
+ g_signal_handlers_disconnect_matched (priv->source, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object);
+ g_object_unref (priv->source);
}
- g_object_unref (priv->source);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_cal_backend_parent_class)->finalize (object);
@@ -376,8 +368,8 @@ e_cal_backend_init (ECalBackend *backend)
backend->priv->clients_mutex = g_mutex_new ();
backend->priv->queries = e_list_new (
- (EListCopyFunc) g_object_ref,
- (EListFreeFunc) g_object_unref, NULL);
+ (EListCopyFunc) NULL,
+ (EListFreeFunc) NULL, NULL);
backend->priv->queries_mutex = g_mutex_new ();
}
diff --git a/calendar/libedata-cal/e-data-cal-factory.c b/calendar/libedata-cal/e-data-cal-factory.c
index a69e323..db9cc1c 100644
--- a/calendar/libedata-cal/e-data-cal-factory.c
+++ b/calendar/libedata-cal/e-data-cal-factory.c
@@ -557,6 +557,15 @@ e_data_cal_factory_init (EDataCalFactory *factory)
}
static void
+unref_backend_cb (gpointer key, gpointer value, gpointer user_data)
+{
+ ECalBackend *backend = value;
+
+ if (backend)
+ g_object_unref (backend);
+}
+
+static void
e_data_cal_factory_finalize (GObject *object)
{
EDataCalFactory *factory = E_DATA_CAL_FACTORY (object);
@@ -565,6 +574,8 @@ e_data_cal_factory_finalize (GObject *object)
g_object_unref (factory->priv->gdbus_object);
+ g_hash_table_foreach (factory->priv->backends, unref_backend_cb, NULL);
+
g_hash_table_destroy (factory->priv->methods);
g_hash_table_destroy (factory->priv->backends);
g_hash_table_destroy (factory->priv->calendars);
diff --git a/calendar/libedata-cal/e-data-cal-view.c b/calendar/libedata-cal/e-data-cal-view.c
index 52de14f..394acf0 100644
--- a/calendar/libedata-cal/e-data-cal-view.c
+++ b/calendar/libedata-cal/e-data-cal-view.c
@@ -328,6 +328,16 @@ impl_DataCalView_stop (EGdbusCalView *object, GDBusMethodInvocation *invocation,
return TRUE;
}
+static gboolean
+impl_DataCalView_dispose (EGdbusCalView *object, GDBusMethodInvocation *invocation, EDataCalView *query)
+{
+ e_gdbus_cal_view_complete_dispose (object, invocation);
+
+ g_object_unref (query);
+
+ return TRUE;
+}
+
static void
e_data_cal_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
@@ -383,6 +393,7 @@ e_data_cal_view_init (EDataCalView *query)
priv->gdbus_object = e_gdbus_cal_view_stub_new ();
g_signal_connect (priv->gdbus_object, "handle-start", G_CALLBACK (impl_DataCalView_start), query);
g_signal_connect (priv->gdbus_object, "handle-stop", G_CALLBACK (impl_DataCalView_stop), query);
+ g_signal_connect (priv->gdbus_object, "handle-dispose", G_CALLBACK (impl_DataCalView_dispose), query);
priv->backend = NULL;
priv->started = FALSE;
@@ -413,6 +424,7 @@ e_data_cal_view_dispose (GObject *object)
priv = query->priv;
if (priv->backend) {
+ e_cal_backend_remove_query (priv->backend, query);
g_object_unref (priv->backend);
priv->backend = NULL;
}
diff --git a/calendar/libedata-cal/e-data-cal-view.xml b/calendar/libedata-cal/e-data-cal-view.xml
index 44ed68a..beb32d9 100644
--- a/calendar/libedata-cal/e-data-cal-view.xml
+++ b/calendar/libedata-cal/e-data-cal-view.xml
@@ -11,6 +11,10 @@
<method name="stop">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_EDataCalView_stop"/>
</method>
+
+ <method name="dispose">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_EDataCalView_dispose"/>
+ </method>
<signal name="ObjectsAdded">
<arg name="objects" type="as"/>
diff --git a/calendar/libegdbus/e-gdbus-egdbuscalview.c b/calendar/libegdbus/e-gdbus-egdbuscalview.c
index 065cd5b..c917c90 100644
--- a/calendar/libegdbus/e-gdbus-egdbuscalview.c
+++ b/calendar/libegdbus/e-gdbus-egdbuscalview.c
@@ -71,6 +71,7 @@ enum
__DONE_SIGNAL,
__START_METHOD,
__STOP_METHOD,
+ __DISPOSE_METHOD,
__LAST_SIGNAL
};
@@ -345,6 +346,7 @@ e_gdbus_cal_view_default_init (EGdbusCalViewIface *iface)
_property_name_to_gname = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (_method_name_to_id, (gpointer) "start", GUINT_TO_POINTER (__START_METHOD));
g_hash_table_insert (_method_name_to_id, (gpointer) "stop", GUINT_TO_POINTER (__STOP_METHOD));
+ g_hash_table_insert (_method_name_to_id, (gpointer) "dispose", GUINT_TO_POINTER (__DISPOSE_METHOD));
g_hash_table_insert (_signal_name_to_id, (gpointer) "ObjectsAdded", GUINT_TO_POINTER (__OBJECTS_ADDED_SIGNAL));
g_hash_table_insert (_signal_name_to_id, (gpointer) "ObjectsModified", GUINT_TO_POINTER (__OBJECTS_MODIFIED_SIGNAL));
g_hash_table_insert (_signal_name_to_id, (gpointer) "ObjectsRemoved", GUINT_TO_POINTER (__OBJECTS_REMOVED_SIGNAL));
@@ -556,6 +558,31 @@ e_gdbus_cal_view_default_init (EGdbusCalViewIface *iface)
1,
G_TYPE_DBUS_METHOD_INVOCATION);
+ /**
+ * EGdbusCalView::handle-dispose:
+ * @object: The exported object emitting the signal.
+ * @invocation: A #GDBusMethodInvocation object that can be used to return a value or error.
+ *
+ * On exported objects, this signal is emitted when a remote process (identified by @invocation) invokes the <literal>dispose</literal> D-Bus method on @object. Use e_gdbus_cal_view_complete_dispose() to return a value or g_dbus_method_invocation_return_error() to return an error.
+ *
+ * The signal is emitted in the thread-default main loop of the thread that e_gdbus_cal_view_register_object() was called from.
+ *
+ * On proxies, this signal is never emitted.
+ *
+ * Returns: %TRUE if you want to handle the method call (will stop further handlers from being called), %FALSE otherwise.
+ */
+ signals[__DISPOSE_METHOD] =
+ g_signal_new ("handle-dispose",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EGdbusCalViewIface, handle_dispose),
+ g_signal_accumulator_true_handled,
+ NULL,
+ _e_gdbus_gdbus_cclosure_marshaller_BOOLEAN__OBJECT,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
/* GObject property definitions for D-Bus properties: */
}
@@ -762,6 +789,106 @@ _out:
}
/**
+ * e_gdbus_cal_view_call_dispose:
+ * @proxy: A #EGdbusCalView.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't care about the result of the method invocation.
+ * @user_data: Data to pass to @callback.
+ *
+ * Invokes the <literal>org.gnome.evolution.dataserver.calendar.CalView.dispose</literal>
+ * D-Bus method on the remote object represented by @proxy.
+ *
+ * This is an asynchronous method. When the operation is finished,
+ * callback will be invoked in the thread-default main loop of the
+ * thread you are calling this method from. You can then call
+ * e_gdbus_cal_view_call_dispose_finish() to get the result of the operation.
+ *
+ * See e_gdbus_cal_view_call_dispose_sync() for the synchronous version of this method.
+ */
+void e_gdbus_cal_view_call_dispose (
+ EGdbusCalView *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GVariant *_params;
+ _params = NULL;
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "dispose",
+ _params,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * e_gdbus_cal_view_call_dispose_finish:
+ * @proxy: A #EGdbusCalView.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to e_gdbus_cal_view_call_dispose().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes invoking the <literal>org.gnome.evolution.dataserver.calendar.CalView.dispose</literal>
+ * D-Bus method on the remote object represented by @proxy.
+ *
+ * Returns: %TRUE if the call succeeded, %FALSE if @error is set.
+ */
+gboolean e_gdbus_cal_view_call_dispose_finish (
+ EGdbusCalView *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ gboolean _ret = FALSE;
+ GVariant *_result;
+ _result = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_result == NULL)
+ goto _out;
+ g_variant_unref (_result);
+ _ret = TRUE;
+_out:
+ return _ret;
+}
+
+/**
+ * e_gdbus_cal_view_call_dispose_sync:
+ * @proxy: A #EGdbusCalView.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <literal>org.gnome.evolution.dataserver.calendar.CalView.dispose</literal>
+ * D-Bus method on the remote object represented by @proxy.
+ *
+ * The calling thread is blocked until a reply is received. See
+ * e_gdbus_cal_view_call_dispose() for the asynchronous version of this method.
+ *
+ * Returns: %TRUE if the call succeeded, %FALSE if @error is set.
+ */
+gboolean e_gdbus_cal_view_call_dispose_sync (
+ EGdbusCalView *proxy,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean _ret = FALSE;
+ GVariant *_params;
+ GVariant *_result;
+ _params = NULL;
+ _result = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "dispose",
+ _params,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_result == NULL)
+ goto _out;
+ g_variant_unref (_result);
+ _ret = TRUE;
+_out:
+ return _ret;
+}
+
+/**
* e_gdbus_cal_view_complete_start:
* @object: A #EGdbusCalView.
* @invocation: A #GDBusMethodInvocation.
@@ -802,6 +929,26 @@ void e_gdbus_cal_view_complete_stop (
}
/**
+ * e_gdbus_cal_view_complete_dispose:
+ * @object: A #EGdbusCalView.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Completes handling the <literal>org.gnome.evolution.dataserver.calendar.CalView.dispose</literal>
+ * D-Bus method invocation by returning a value.
+ *
+ * If you want to return an error, use g_dbus_method_invocation_return_error()
+ * or similar instead.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void e_gdbus_cal_view_complete_dispose (
+ EGdbusCalView *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation, NULL);
+}
+
+/**
* e_gdbus_cal_view_emit_objects_added:
* @object: A #EGdbusCalView.
* @arg_objects: Signal parameter.
@@ -1029,10 +1176,20 @@ static const GDBusMethodInfo e_gdbus_cal_view_method_stop =
(GDBusAnnotationInfo **) NULL,
};
+static const GDBusMethodInfo e_gdbus_cal_view_method_dispose =
+{
+ -1,
+ (gchar *) "dispose",
+ (GDBusArgInfo **) NULL,
+ (GDBusArgInfo **) NULL,
+ (GDBusAnnotationInfo **) NULL,
+};
+
static const GDBusMethodInfo * const e_gdbus_cal_view_method_info_pointers[] =
{
&e_gdbus_cal_view_method_start,
&e_gdbus_cal_view_method_stop,
+ &e_gdbus_cal_view_method_dispose,
NULL
};
@@ -1083,6 +1240,18 @@ handle_method_call (GDBusConnection *connection,
}
break;
+ case __DISPOSE_METHOD:
+ {
+ EGdbusCalView *object = E_GDBUS_CAL_VIEW (user_data);
+ gboolean handled;
+ g_signal_emit (object,
+ signals[method_id],
+ 0, invocation, &handled);
+ if (!handled)
+ goto not_implemented;
+ }
+ break;
+
default:
not_implemented:
g_dbus_method_invocation_return_error (invocation,
diff --git a/calendar/libegdbus/e-gdbus-egdbuscalview.h b/calendar/libegdbus/e-gdbus-egdbuscalview.h
index 2dde043..b3361d0 100644
--- a/calendar/libegdbus/e-gdbus-egdbuscalview.h
+++ b/calendar/libegdbus/e-gdbus-egdbuscalview.h
@@ -35,6 +35,7 @@ typedef struct _EGdbusCalView EGdbusCalView; /* Dummy typedef */
* @done: Handler for the #EGdbusCalView::done signal.
* @handle_start: Handler for the #EGdbusCalView::handle-start signal.
* @handle_stop: Handler for the #EGdbusCalView::handle-stop signal.
+ * @handle_dispose: Handler for the #EGdbusCalView::handle-dispose signal.
*
* Virtual table.
*/
@@ -189,6 +190,9 @@ struct _EGdbusCalViewIface
gboolean (*handle_stop) (
EGdbusCalView *object,
GDBusMethodInvocation *invocation);
+ gboolean (*handle_dispose) (
+ EGdbusCalView *object,
+ GDBusMethodInvocation *invocation);
};
/* C Bindings for properties */
@@ -226,6 +230,22 @@ gboolean e_gdbus_cal_view_call_stop_sync (
GCancellable *cancellable,
GError **error);
+void e_gdbus_cal_view_call_dispose (
+ EGdbusCalView *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean e_gdbus_cal_view_call_dispose_finish (
+ EGdbusCalView *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean e_gdbus_cal_view_call_dispose_sync (
+ EGdbusCalView *proxy,
+ GCancellable *cancellable,
+ GError **error);
+
/* D-Bus Methods Completion Helpers */
void e_gdbus_cal_view_complete_start (
EGdbusCalView *object,
@@ -235,6 +255,10 @@ void e_gdbus_cal_view_complete_stop (
EGdbusCalView *object,
GDBusMethodInvocation *invocation);
+void e_gdbus_cal_view_complete_dispose (
+ EGdbusCalView *object,
+ GDBusMethodInvocation *invocation);
+
/* D-Bus Signal Emission Helpers */
void e_gdbus_cal_view_emit_objects_added (
EGdbusCalView *object,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]