Blame SOURCES/0001-UPnP-Disconnect-signal-handlers-during-destruction.patch

62f96b
From 916daa1bf04bfb1d8823c3f677a021bf41df1db0 Mon Sep 17 00:00:00 2001
62f96b
From: Debarshi Ray <debarshir@freedesktop.org>
62f96b
Date: Tue, 20 Jan 2015 13:59:33 +0100
62f96b
Subject: [PATCH] Disconnect signal handlers during destruction
62f96b
62f96b
A GUPnPContextManager can outlive a dlr_upnp_t because it might be
62f96b
using asynchronous operations during its construction (eg.,
62f96b
GUPnPNetworkManager) which retain references to it. This can be
62f96b
demonstrated if the service is spawned as a result of the following
62f96b
command:
62f96b
$ gdbus call \
62f96b
    --session \
62f96b
    --dest com.intel.dleyna-renderer \
62f96b
    --object-path /com/intel/dLeynaRenderer \
62f96b
    --method com.intel.dLeynaRenderer.Manager.Release
62f96b
62f96b
This leads to the signal handlers being invoked with an invalid
62f96b
dlr_upnp_t and the outcome is a crash.
62f96b
62f96b
To avoid this, we should disconnect the callbacks listening to the
62f96b
context manager and the control points belonging to it.
62f96b
---
62f96b
 libdleyna/renderer/upnp.c | 20 ++++++++++++++++++++
62f96b
 1 file changed, 20 insertions(+)
62f96b
62f96b
diff --git a/libdleyna/renderer/upnp.c b/libdleyna/renderer/upnp.c
62f96b
index 17cbda720bc1..707dc09aaf5a 100644
62f96b
--- a/libdleyna/renderer/upnp.c
62f96b
+++ b/libdleyna/renderer/upnp.c
62f96b
@@ -45,6 +45,7 @@ struct dlr_upnp_t_ {
62f96b
 	void *user_data;
62f96b
 	GHashTable *server_udn_map;
62f96b
 	GHashTable *server_uc_map;
62f96b
+	GList *cps;
62f96b
 	dlr_host_service_t *host_service;
62f96b
 };
62f96b
 
62f96b
@@ -352,6 +353,7 @@ static void prv_on_context_available(GUPnPContextManager *context_manager,
62f96b
 
62f96b
 	gssdp_resource_browser_set_active(GSSDP_RESOURCE_BROWSER(cp), TRUE);
62f96b
 	gupnp_context_manager_manage_control_point(upnp->context_manager, cp);
62f96b
+	upnp->cps = g_list_prepend (upnp->cps, g_object_ref (cp));
62f96b
 	g_object_unref(cp);
62f96b
 }
62f96b
 
62f96b
@@ -390,10 +392,28 @@ dlr_upnp_t *dlr_upnp_new(dleyna_connector_id_t connection,
62f96b
 void dlr_upnp_delete(dlr_upnp_t *upnp)
62f96b
 {
62f96b
 	if (upnp) {
62f96b
+		GList *l;
62f96b
+
62f96b
+		for (l = upnp->cps; l != NULL; l = l->next) {
62f96b
+			GUPnPControlPoint *cp = GUPNP_CONTROL_POINT (l->data);
62f96b
+
62f96b
+			g_signal_handlers_disconnect_by_func (cp,
62f96b
+							      prv_server_available_cb,
62f96b
+							      upnp);
62f96b
+			g_signal_handlers_disconnect_by_func (cp,
62f96b
+							      prv_server_unavailable_cb,
62f96b
+							      upnp);
62f96b
+		}
62f96b
+
62f96b
+		g_signal_handlers_disconnect_by_func (upnp->context_manager,
62f96b
+						      prv_on_context_available,
62f96b
+						      upnp);
62f96b
+
62f96b
 		dlr_host_service_delete(upnp->host_service);
62f96b
 		g_object_unref(upnp->context_manager);
62f96b
 		g_hash_table_unref(upnp->server_udn_map);
62f96b
 		g_hash_table_unref(upnp->server_uc_map);
62f96b
+		g_list_free_full (upnp->cps, g_object_unref);
62f96b
 
62f96b
 		g_free(upnp);
62f96b
 	}
62f96b
-- 
62f96b
2.9.5
62f96b