After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 669729 - gupnp_service_proxy_begin_action returns invalid pointer on synchronous error
gupnp_service_proxy_begin_action returns invalid pointer on synchronous error
Status: RESOLVED FIXED
Product: GUPnP
Classification: Other
Component: gupnp
0.18.x
Other All
: Normal normal
: ---
Assigned To: GUPnP Maintainers
GUPnP Maintainers
Depends on:
Blocks:
 
 
Reported: 2012-02-09 07:57 UTC by Branislav Katreniak
Modified: 2013-10-16 13:09 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Call action callback through idle on error (1.58 KB, patch)
2013-08-18 10:11 UTC, Jens Georg
committed Details | Review

Description Branislav Katreniak 2012-02-09 07:57:11 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);
Comment 1 Jens Georg 2012-02-24 14:59:54 UTC
(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.
Comment 2 Jens Georg 2012-02-24 15:16:06 UTC
(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.
Comment 3 Branislav Katreniak 2012-02-24 15:48:09 UTC
Application expects callback for every action. It cannot assume that in certain error conditions the callback comes synchronously.
Comment 4 Jens Georg 2013-08-18 10:11:02 UTC
Created attachment 252100 [details] [review]
Call action callback through idle on error
Comment 5 Jens Georg 2013-10-16 13:09:30 UTC
Attachment 252100 [details] pushed as e914903 - Call action callback through idle on error