From 916daa1bf04bfb1d8823c3f677a021bf41df1db0 Mon Sep 17 00:00:00 2001 From: Debarshi Ray 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