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