Merge branch 'gtask-return-literal' into 'main'

gtask: Add g_task_return_new_error_literal()

See merge request GNOME/glib!3771
This commit is contained in:
Philip Withnall 2023-12-20 16:53:20 +00:00
commit 30d6e911c4
18 changed files with 175 additions and 75 deletions

View File

@ -721,8 +721,8 @@ g_app_info_launch_uris_async (GAppInfo *appinfo,
task = g_task_new (appinfo, cancellable, callback, user_data);
g_task_set_source_tag (task, g_app_info_launch_uris_async);
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Operation not supported for the current backend.");
g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Operation not supported for the current backend.");
g_object_unref (task);
return;

View File

@ -1828,7 +1828,7 @@ send_message_data_deliver_error (GTask *task,
send_message_with_reply_cleanup (task, TRUE);
CONNECTION_UNLOCK (connection);
g_task_return_new_error (task, domain, code, "%s", message);
g_task_return_new_error_literal (task, domain, code, message);
g_object_unref (task);
}
@ -2386,10 +2386,10 @@ cancel_method_on_close (gpointer key, gpointer value, gpointer user_data)
if (data->delivered)
return FALSE;
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_CLOSED,
_("The connection is closed"));
g_task_return_new_error_literal (task,
G_IO_ERROR,
G_IO_ERROR_CLOSED,
_("The connection is closed"));
/* Ask send_message_with_reply_cleanup not to remove the element from the
* hash table - we're in the middle of a foreach; that would be unsafe.

View File

@ -1030,10 +1030,12 @@ write_message_continue_writing (MessageToWriteData *data)
if (!(data->worker->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING))
{
GTask *task = g_steal_pointer (&data->task);
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_FAILED,
"Tried sending a file descriptor but remote peer does not support this capability");
g_task_return_new_error_literal (task,
G_IO_ERROR,
G_IO_ERROR_FAILED,
"Tried sending a file descriptor "
"but remote peer does not support "
"this capability");
g_clear_object (&task);
goto out;
}

View File

@ -7721,9 +7721,9 @@ query_default_handler_query_app_info_for_type_cb (GObject *object,
}
else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_task_return_new_error (task,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"%s", error->message);
g_task_return_new_error_literal (task,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
error->message);
}
else
{
@ -7774,10 +7774,10 @@ query_default_handler_query_info_cb (GObject *object,
}
else
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
_("No application is registered as handling this file"));
g_task_return_new_error_literal (task,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
_("No application is registered as handling this file"));
}
g_object_unref (info);

View File

@ -285,8 +285,9 @@ can_reach_async_got_address (GObject *object,
else
{
/* Resolved all addresses, none matched */
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE,
_("Host unreachable"));
g_task_return_new_error_literal (task, G_IO_ERROR,
G_IO_ERROR_HOST_UNREACHABLE,
_("Host unreachable"));
g_object_unref (task);
return;
}
@ -321,8 +322,8 @@ g_network_monitor_base_can_reach_async (GNetworkMonitor *monitor,
if (g_hash_table_size (G_NETWORK_MONITOR_BASE (monitor)->priv->networks) == 0)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE,
_("Network unreachable"));
g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE,
_("Network unreachable"));
g_object_unref (task);
return;
}

View File

@ -561,9 +561,9 @@ can_reach_done (GObject *source,
if (reachable)
g_task_return_boolean (task, TRUE);
else
g_task_return_new_error (task,
G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE,
"Can't reach host");
g_task_return_new_error_literal (task,
G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE,
"Can't reach host");
g_object_unref (task);
}

View File

@ -182,11 +182,11 @@ response_received (GDBusConnection *connection,
g_task_return_boolean (task, TRUE);
break;
case XDG_DESKTOP_PORTAL_CANCELLED:
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Launch cancelled");
g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Launch cancelled");
break;
case XDG_DESKTOP_PORTAL_FAILED:
default:
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Launch failed");
g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Launch failed");
break;
}

View File

@ -1764,9 +1764,9 @@ g_output_stream_splice_async (GOutputStream *stream,
if (g_input_stream_is_closed (source))
{
g_task_return_new_error (task,
G_IO_ERROR, G_IO_ERROR_CLOSED,
_("Source stream is already closed"));
g_task_return_new_error_literal (task,
G_IO_ERROR, G_IO_ERROR_CLOSED,
_("Source stream is already closed"));
g_object_unref (task);
return;
}

View File

@ -343,9 +343,14 @@ complete_async (GTask *task)
priv->last_error = NULL;
}
else if (!priv->ever_enumerated)
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, _("Unspecified proxy lookup failure"));
{
g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Unspecified proxy lookup failure"));
}
else
g_task_return_pointer (task, NULL, NULL);
{
g_task_return_pointer (task, NULL, NULL);
}
priv->ever_enumerated = TRUE;

View File

@ -724,10 +724,10 @@ nego_reply_read_cb (GObject *source,
if (read == 0)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_CONNECTION_CLOSED,
"Connection to SOCKSv5 proxy server lost");
g_task_return_new_error_literal (task,
G_IO_ERROR,
G_IO_ERROR_CONNECTION_CLOSED,
"Connection to SOCKSv5 proxy server lost");
g_object_unref (task);
return;
}
@ -837,10 +837,10 @@ auth_reply_read_cb (GObject *source,
if (read == 0)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_CONNECTION_CLOSED,
"Connection to SOCKSv5 proxy server lost");
g_task_return_new_error_literal (task,
G_IO_ERROR,
G_IO_ERROR_CONNECTION_CLOSED,
"Connection to SOCKSv5 proxy server lost");
g_object_unref (task);
return;
}
@ -949,10 +949,10 @@ connect_reply_read_cb (GObject *source,
if (read == 0)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_CONNECTION_CLOSED,
"Connection to SOCKSv5 proxy server lost");
g_task_return_new_error_literal (task,
G_IO_ERROR,
G_IO_ERROR_CONNECTION_CLOSED,
"Connection to SOCKSv5 proxy server lost");
g_object_unref (task);
return;
}
@ -1019,10 +1019,10 @@ connect_addr_len_read_cb (GObject *source,
if (read == 0)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_CONNECTION_CLOSED,
"Connection to SOCKSv5 proxy server lost");
g_task_return_new_error_literal (task,
G_IO_ERROR,
G_IO_ERROR_CONNECTION_CLOSED,
"Connection to SOCKSv5 proxy server lost");
g_object_unref (task);
return;
}
@ -1055,10 +1055,10 @@ connect_addr_read_cb (GObject *source,
if (read == 0)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_CONNECTION_CLOSED,
"Connection to SOCKSv5 proxy server lost");
g_task_return_new_error_literal (task,
G_IO_ERROR,
G_IO_ERROR_CONNECTION_CLOSED,
"Connection to SOCKSv5 proxy server lost");
g_object_unref (task);
return;
}

View File

@ -2031,7 +2031,8 @@ g_task_propagate_boolean (GTask *task,
* Call g_error_copy() on the error if you need to keep a local copy
* as well.
*
* See also g_task_return_new_error().
* See also [method@Gio.Task.return_new_error],
* [method@Gio.Task.return_new_error_literal].
*
* Since: 2.36
*/
@ -2130,6 +2131,32 @@ g_task_return_new_error (GTask *task,
g_task_return_error (task, error);
}
/**
* g_task_return_new_error_literal:
* @task: a #GTask.
* @domain: a #GQuark.
* @code: an error code.
* @message: an error message
*
* Sets @tasks result to a new [type@GLib.Error] created from @domain, @code,
* @message and completes the task.
*
* See [method@Gio.Task.return_pointer] for more discussion of exactly what
* completing the task means.
*
* See also [method@Gio.Task.return_new_error].
*
* Since: 2.80
*/
void
g_task_return_new_error_literal (GTask *task,
GQuark domain,
gint code,
const char *message)
{
g_task_return_error (task, g_error_new_literal (domain, code, message));
}
/**
* g_task_return_error_if_cancelled:
* @task: a #GTask

View File

@ -175,6 +175,12 @@ void g_task_return_new_error (GTask *task,
gint code,
const char *format,
...) G_GNUC_PRINTF (4, 5);
GIO_AVAILABLE_IN_2_80
void g_task_return_new_error_literal (GTask *task,
GQuark domain,
gint code,
const char *message);
GIO_AVAILABLE_IN_2_64
void g_task_return_value (GTask *task,
GValue *result);

View File

@ -1448,8 +1448,10 @@ timeout_cb (gpointer user_data)
g_mutex_unlock (&data->lock);
if (should_return)
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
_("Socket I/O timed out"));
{
g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
_("Socket I/O timed out"));
}
/* Signal completion of the task. */
g_mutex_lock (&data->lock);

View File

@ -262,7 +262,7 @@ eject_unmount_done (GObject *source,
{
if (!g_subprocess_get_successful (subprocess))
/* ...but bad exit code */
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "%s", stderr_str);
g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_FAILED, stderr_str);
else
/* ...and successful exit code */
g_task_return_boolean (task, TRUE);

View File

@ -287,7 +287,7 @@ eject_mount_done (GObject *source,
{
if (!g_subprocess_get_successful (subprocess))
/* ...but bad exit code */
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "%s", stderr_str);
g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_FAILED, stderr_str);
else
{
/* ...and successful exit code */

View File

@ -797,9 +797,9 @@ g_fake_resolver_lookup_by_name_async (GResolver *resolver,
}
else
{
g_task_return_new_error (task,
G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
"Not found");
g_task_return_new_error_literal (task,
G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
"Not found");
}
g_object_unref (task);
}

View File

@ -129,12 +129,19 @@ test_basic (void)
/* test_error */
typedef struct {
GQuark expected_domain;
int expected_code;
char *expected_message;
gssize int_result;
} TaskErrorResult;
static void
error_callback (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
gssize *result_out = user_data;
TaskErrorResult *result_inout = user_data;
GError *error = NULL;
g_assert (object == NULL);
@ -143,13 +150,12 @@ error_callback (GObject *object,
g_assert (g_task_had_error (G_TASK (result)));
g_assert_false (g_task_get_completed (G_TASK (result)));
*result_out = g_task_propagate_int (G_TASK (result), &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
result_inout->int_result = g_task_propagate_int (G_TASK (result), &error);
g_assert_error (error, result_inout->expected_domain, result_inout->expected_code);
g_assert_cmpstr (error->message, ==, result_inout->expected_message);
g_error_free (error);
g_assert (g_task_had_error (G_TASK (result)));
g_main_loop_quit (loop);
}
static gboolean
@ -159,7 +165,7 @@ error_return (gpointer user_data)
g_task_return_new_error (task,
G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed");
"Failed %p", task);
g_object_unref (task);
return FALSE;
@ -177,15 +183,17 @@ static void
test_error (void)
{
GTask *task;
gssize result;
TaskErrorResult result;
gboolean first_task_data_destroyed = FALSE;
gboolean second_task_data_destroyed = FALSE;
gboolean notification_emitted = FALSE;
task = g_task_new (NULL, NULL, error_callback, &result);
result = (TaskErrorResult){
.expected_domain = G_IO_ERROR,
.expected_code = G_IO_ERROR_FAILED,
.expected_message = g_strdup_printf ("Failed %p", task),
};
g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
g_signal_connect (task, "notify::completed",
(GCallback) completed_cb, &notification_emitted);
g_assert (first_task_data_destroyed == FALSE);
g_task_set_task_data (task, &first_task_data_destroyed, error_destroy_notify);
@ -197,12 +205,59 @@ test_error (void)
g_assert (second_task_data_destroyed == FALSE);
g_idle_add (error_return, task);
g_main_loop_run (loop);
wait_for_completed_notification (task);
g_assert_cmpint (result, ==, -1);
g_assert_cmpint (result.int_result, ==, -1);
g_assert (second_task_data_destroyed == TRUE);
g_assert_true (notification_emitted);
g_assert (task == NULL);
g_free (result.expected_message);
}
static void
test_error_literal (void)
{
GTask *task;
TaskErrorResult result;
task = g_task_new (NULL, NULL, error_callback, &result);
result = (TaskErrorResult){
.expected_domain = G_IO_ERROR,
.expected_code = G_IO_ERROR_FAILED,
.expected_message = "Literal Failure",
};
g_task_return_new_error_literal (task,
result.expected_domain,
result.expected_code,
"Literal Failure");
wait_for_completed_notification (task);
g_assert_cmpint (result.int_result, ==, -1);
g_assert_finalize_object (task);
}
static void
test_error_literal_from_variable (void)
{
GTask *task;
TaskErrorResult result;
task = g_task_new (NULL, NULL, error_callback, &result);
result = (TaskErrorResult){
.expected_domain = G_IO_ERROR,
.expected_code = G_IO_ERROR_FAILED,
.expected_message = "Literal Failure",
};
g_task_return_new_error_literal (task,
result.expected_domain,
result.expected_code,
result.expected_message);
wait_for_completed_notification (task);
g_assert_cmpint (result.int_result, ==, -1);
g_assert_finalize_object (task);
}
/* test_return_from_same_iteration: calling g_task_return_* from the
@ -2524,6 +2579,8 @@ main (int argc, char **argv)
g_test_add_func ("/gtask/basic", test_basic);
g_test_add_func ("/gtask/error", test_error);
g_test_add_func ("/gtask/error-literal", test_error_literal);
g_test_add_func ("/gtask/error-literal-from-variable", test_error_literal_from_variable);
g_test_add_func ("/gtask/return-from-same-iteration", test_return_from_same_iteration);
g_test_add_func ("/gtask/return-from-toplevel", test_return_from_toplevel);
g_test_add_func ("/gtask/return-from-anon-thread", test_return_from_anon_thread);

View File

@ -149,7 +149,7 @@ test_interaction_ask_password_async_failure (GTlsInteraction *interaction,
task = g_task_new (self, cancellable, callback, user_data);
g_task_return_new_error (task, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
g_task_return_new_error_literal (task, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
g_object_unref (task);
}
@ -348,7 +348,7 @@ test_interaction_request_certificate_async_failure (GTlsInteraction *interact
task = g_task_new (self, cancellable, callback, user_data);
g_task_return_new_error (task, G_FILE_ERROR, G_FILE_ERROR_NOENT, "Another message");
g_task_return_new_error_literal (task, G_FILE_ERROR, G_FILE_ERROR_NOENT, "Another message");
g_object_unref (task);
}