mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-02 15:33:39 +02:00
gtask: Emit a debug message if a GTask is finalised without returning
This typically indicates a bug in the program, where a GTask has been created, but a bug in the control flow has caused it to not return a value. There is one situation where it might be legitimate to finalise a GTask without returning: if an error happens in your *_async() start function after you’ve created a GTask, but before the async operation returns to the main loop; and you report the error using g_task_report_*error() rather than reporting it using the newly constructed GTask. Another situation is where you are just using GTask as a convenient way to move some work to another thread, without the complexity of creating and running your own thread pool. GDBus does this with g_dbus_interface_method_dispatch_helper(), for example. In most other cases, it’s a bug. Emit a debug message about it, but not a full-blown warning, as that would create noise in the legitimate cases. Signed-off-by: Philip Withnall <withnall@endlessm.com>
This commit is contained in:
committed by
Philip Withnall
parent
1d7dfb68e8
commit
fe89940572
32
gio/gtask.c
32
gio/gtask.c
@@ -64,6 +64,10 @@
|
||||
* #GTask was constructed to be running at least until the task has completed
|
||||
* and its data has been freed.
|
||||
*
|
||||
* If a #GTask has been constructed and its callback set, it is an error to
|
||||
* not call `g_task_return_*()` on it. GLib will warn at runtime if this happens
|
||||
* (since 2.76).
|
||||
*
|
||||
* Here is an example for using GTask as a GAsyncResult:
|
||||
* |[<!-- language="C" -->
|
||||
* typedef struct {
|
||||
@@ -659,6 +663,34 @@ g_task_finalize (GObject *object)
|
||||
{
|
||||
GTask *task = G_TASK (object);
|
||||
|
||||
/* Warn if a #GTask is finalised without g_task_return() ever having been
|
||||
* called on it.
|
||||
*
|
||||
* Tasks without a callback or which are run in g_task_run_in_thread{,_sync}()
|
||||
* only trigger a debug message as that’s sometimes used as a pattern for
|
||||
* running work in a worker thread without caring about the result. */
|
||||
if (!task->ever_returned)
|
||||
{
|
||||
gchar *owned_task_name = NULL;
|
||||
const gchar *task_name = g_task_get_name (task);
|
||||
|
||||
if (task_name == NULL)
|
||||
task_name = owned_task_name = g_strdup_printf ("%p", task);
|
||||
|
||||
if (task->callback != NULL && !G_TASK_IS_THREADED (task))
|
||||
g_critical ("GTask %s (source object: %p, source tag: %p) finalized without "
|
||||
"ever returning (using g_task_return_*()). This potentially "
|
||||
"indicates a bug in the program.",
|
||||
task_name, task->source_object, task->source_tag);
|
||||
else
|
||||
g_debug ("GTask %s (source object: %p, source tag: %p) finalized without "
|
||||
"ever returning (using g_task_return_*()). This potentially "
|
||||
"indicates a bug in the program.",
|
||||
task_name, task->source_object, task->source_tag);
|
||||
|
||||
g_free (owned_task_name);
|
||||
}
|
||||
|
||||
g_clear_object (&task->source_object);
|
||||
g_clear_object (&task->cancellable);
|
||||
if (!task->name_is_static)
|
||||
|
Reference in New Issue
Block a user