gtask: Return cancelled tasks asynchronously

Once cancelled, a GTask's callback should not only be invoked
asynchronously with respect to the creation of the task, but also with
respect to the GCancellable::cancelled handler. This is particularly
relevant in cases where the cancellation happened in the same thread
where the task is running.

Spotted by Dan Winship and Michael Catanzaro.

Closes https://gitlab.gnome.org/GNOME/glib/issues/1608
This commit is contained in:
Debarshi Ray 2018-12-03 20:10:41 +01:00 committed by Philip Withnall
parent 0f8a4f61b0
commit 6f3d57d2ee

View File

@ -1,6 +1,6 @@
/* GIO - GLib Input, Output and Streaming Library /* GIO - GLib Input, Output and Streaming Library
* *
* Copyright 2011 Red Hat, Inc. * Copyright 2011-2018 Red Hat, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -1260,9 +1260,18 @@ g_task_return (GTask *task,
*/ */
if (g_source_get_time (source) > task->creation_time) if (g_source_get_time (source) > task->creation_time)
{ {
g_task_return_now (task); /* Finally, if the task has been cancelled, we shouldn't
g_object_unref (task); * return synchronously from inside the
return; * GCancellable::cancelled handler. It's easier to run
* another iteration of the main loop than tracking how the
* cancellation was handled.
*/
if (!g_cancellable_is_cancelled (task->cancellable))
{
g_task_return_now (task);
g_object_unref (task);
return;
}
} }
} }