GNOME Bugzilla – Bug 669729
gupnp_service_proxy_begin_action returns invalid pointer on synchronous error
Last modified: 2013-10-16 13:09:34 UTC
Documentation for method gupnp_service_proxy_begin_action() Returns : A GUPnPServiceProxyAction handle. This will be freed in call to gupnp_service_proxy_cancel_action() or gupnp_service_proxy_end_action_valist(). [transfer none] Method gupnp_service_proxy_begin_action() calls gupnp_service_proxy_begin_action_valist and begin_action_msg Method begin_action_msg can synchronously fail on number of reasons. In this case method gupnp_service_proxy_begin_action_valist calls callback and returns pointer to action. if (ret->error) { callback (proxy, ret, user_data); return ret; } But it is expected that callback calls gupnp_service_proxy_end_action and thus frees the action. The pointer to returned action is invalid. I found this problem by proof-reading the source code. It should happen when upnp server provides wrong description (empty service type / control uri that cannot be parsed). To solve this issue I propose to call the application callback asynchronously. It does not change the documented API. And application must be prepared for asynchronous invocation anyway. I will prepare patch if maintainer(s) confirm this issue and agree with the proposed solution. I am new to glib programming. What is the best way to enqueue the method to the event loop? Is g_timeout_add with 1 millisecond fine? +static gboolean callback_timeout_cb (gpointer userdata) +{ + GUPnPServiceProxyAction *action = (GUPnPServiceProxyAction *) userdata; + action->callback (action->proxy, action, action->user_data); + return FALSE; +} - callback (proxy, ret, user_data); + g_timeout_add (1, callback_timeout_cb, ret);
(In reply to comment #0) > > I will prepare patch if maintainer(s) confirm this issue and agree with the > proposed solution. I'm not sure that there is a problem; I'm preparing a set of unittests to check the situation and get back to you. > > I am new to glib programming. What is the best way to enqueue the method to the > event loop? Is g_timeout_add with 1 millisecond fine? No, usually one uses g_idle_add_* or g_main_context_invoke.
(In reply to comment #1) > (In reply to comment #0) > > > > I will prepare patch if maintainer(s) confirm this issue and agree with the > > proposed solution. > Ah, right. Now I understand it. The callback could free the action and the returned pointer would be dangling. But we cannot guarantee that the callback does that. We should at least document that, but I don't know if there's a safe way to fix this behaviour in a way that doesn't break current code.
Application expects callback for every action. It cannot assume that in certain error conditions the callback comes synchronously.
Created attachment 252100 [details] [review] Call action callback through idle on error
Attachment 252100 [details] pushed as e914903 - Call action callback through idle on error