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 764163 - g_task_had_error doesn't remember the error after g_task_propagate_*
g_task_had_error doesn't remember the error after g_task_propagate_*
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: gio
2.46.x
Other All
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2016-03-24 17:43 UTC by Debarshi Ray
Modified: 2016-05-04 07:36 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gtask: Don't forget about the error after g_task_propagate_* (1.10 KB, patch)
2016-03-24 17:44 UTC, Debarshi Ray
none Details | Review
gio/tests/task: Ensure that g_task_had_error doesn't forget the error (4.07 KB, patch)
2016-03-24 18:08 UTC, Debarshi Ray
committed Details | Review
gtask: Don't forget about the error after g_task_propagate_* (1.52 KB, patch)
2016-04-28 14:34 UTC, Debarshi Ray
committed Details | Review

Description Debarshi Ray 2016-03-24 17:43:22 UTC
The use of past tense in the method name (ie. g_task_had_error) and in the documentation (ie. "Tests if task resulted in an error") makes one assume that it won't forget about any errors that might have occured. Except, in reality, it does, once you have called any of the g_task_propagate_* methods.

We should either fix the code or the documentation.
Comment 1 Debarshi Ray 2016-03-24 17:44:18 UTC
Created attachment 324696 [details] [review]
gtask: Don't forget about the error after g_task_propagate_*
Comment 2 Debarshi Ray 2016-03-24 18:08:51 UTC
Created attachment 324698 [details] [review]
gio/tests/task: Ensure that g_task_had_error doesn't forget the error
Comment 3 Christophe Fergeau 2016-03-25 08:27:34 UTC
Review of attachment 324696 [details] [review]:

I don't know if that matters, but this will change behaviour of calling g_task_propagate_error() twice on the same GTask (before, the second call was returning FALSE and no GError set, after this patch, it will return TRUE and set a GError),
Comment 4 Debarshi Ray 2016-03-27 12:09:16 UTC
(In reply to Christophe Fergeau from comment #3)
> Review of attachment 324696 [details] [review] [review]:
> 
> I don't know if that matters, but this will change behaviour of calling
> g_task_propagate_error()

g_task_propagate_error is not public API, and its internal users didn't appear to be unduly affected.

> twice on the same GTask (before, the second call
> was returning FALSE and no GError set, after this patch, it will return TRUE
> and set a GError),

Hmm... g_task_propagate_pointer is public and is supposed to be only called once:
https://developer.gnome.org/gio/stable/GTask.html#g-task-propagate-pointer
Comment 5 Dan Winship 2016-03-28 14:47:26 UTC
I think this is a documentation bug, unless you have a strong use case for having it keep working after the propagate call?

The expected use case was mostly for when the return-value-on-error is also a valid return value on non-error (eg, GSList *get_foo() returns NULL on error, but will also return NULL if the list is empty), and you have to distinguish between the cases in the finish function. Eg:

    GError *my_error = NULL;
    gpointer ret;

    ret = g_task_propagate_pointer (task, &my_error);
    if (my_error) {
        // do some cleanup here or whatever
        ...
        g_error_propagate (error, my_error);
    }
    return ret;

Using g_task_had_error() lets you simplify that to:

    if (g_task_had_error (task)) {
        // do some cleanup here or whatever
        ...
    }
    return g_task_propagate_pointer (task, error);
Comment 6 Debarshi Ray 2016-03-29 15:46:45 UTC
Here is an example, but I can live with replacing g_task_had_error with "if (array == NULL)":

gboolean
foo_object_do_something_finish (FooObject *self,
                                GAsyncResult *res,
                                gsize *out_var_1,
                                gsize *out_var_2,
                                GError **error)
{
  GTask *task = G_TASK (res);
  gboolean ret_val = FALSE;
  gsize *array;

  /* g_return_val_if_fail guards */

  array = g_task_propagate_pointer (task, error);
  if (g_task_had_error (task))
    goto out;

  ret_val = TRUE;

  if (out_var_1 != NULL)
    *out_var_1 = array[0];
  if (out_var_2 != NULL)
    *out_var_2 = array[1];

 out:
  return ret_val;
}
Comment 7 Allison Karlitskaya (desrt) 2016-04-28 13:43:30 UTC
I don't like keeping the error around.

If there absolutely is a strong case for using had_error() after stealing the GError away, I'd prefer we had a separate boolean for it.  We could also entertain the (strange) possibility of allowing:

  g_task_return_error (task, NULL);


I'd also be OK with a docs clarification.
Comment 8 Debarshi Ray 2016-04-28 14:34:07 UTC
Created attachment 326948 [details] [review]
gtask: Don't forget about the error after g_task_propagate_*
Comment 9 Dan Winship 2016-05-03 18:04:48 UTC
Comment on attachment 326948 [details] [review]
gtask: Don't forget about the error after g_task_propagate_*

hm... odd, but I guess it simplifies things since error could be set from multiple places
Comment 10 Debarshi Ray 2016-05-04 07:36:05 UTC
Comment on attachment 324698 [details] [review]
gio/tests/task: Ensure that g_task_had_error doesn't forget the error

Pushed to master.
Comment 11 Debarshi Ray 2016-05-04 07:36:23 UTC
Comment on attachment 326948 [details] [review]
gtask: Don't forget about the error after g_task_propagate_*

Pushed to master.