Merge branch 'cancel' into 'main'

gdbusconnection: don't cache G_IO_ERROR_CANCELLED errors

See merge request GNOME/glib!3663
This commit is contained in:
Philip Withnall 2023-12-11 14:17:14 +00:00
commit 7bea669665
2 changed files with 85 additions and 1 deletions

View File

@ -2642,7 +2642,26 @@ initable_init (GInitable *initable,
g_propagate_error (error, g_error_copy (connection->initialization_error));
}
g_atomic_int_or (&connection->atomic_flags, FLAG_INITIALIZED);
/* Don't cache canceled errors. Otherwise other concurrent users of the same connection
* object will be canceled as well. */
if (g_error_matches (connection->initialization_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
if (connection->worker != NULL)
{
_g_dbus_worker_stop (connection->worker);
connection->worker = NULL;
if (alive_connections != NULL)
g_warn_if_fail (g_hash_table_remove (alive_connections, connection));
}
g_clear_error (&connection->initialization_error);
g_clear_object (&connection->stream);
g_clear_object (&connection->auth);
g_clear_object (&connection->credentials);
g_clear_pointer (&connection->guid, g_free);
connection->capabilities = 0;
}
else
g_atomic_int_or (&connection->atomic_flags, FLAG_INITIALIZED);
g_mutex_unlock (&connection->init_lock);
return ret;

View File

@ -1215,6 +1215,70 @@ test_connection_serials (void)
/* ---------------------------------------------------------------------------------------------------- */
static void
get_connection_cb_expect_cancel (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GDBusConnection *c;
GError *error;
error = NULL;
c = g_bus_get_finish (res, &error);
/* unref here to avoid timeouts when the test fails */
if (c)
g_object_unref (c);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
g_assert_null (c);
g_error_free (error);
}
static void
get_connection_cb_expect_success (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GDBusConnection *c;
GError *error;
error = NULL;
c = g_bus_get_finish (res, &error);
g_assert_no_error (error);
g_assert_nonnull (c);
g_main_loop_quit (loop);
g_object_unref (c);
}
static void
test_connection_cancel (void)
{
GCancellable *cancellable, *cancellable2;
g_test_summary ("Test that cancelling one of two racing g_bus_get() calls does not cancel the other one");
session_bus_up ();
cancellable = g_cancellable_new ();
cancellable2 = g_cancellable_new ();
g_bus_get (G_BUS_TYPE_SESSION, cancellable, get_connection_cb_expect_cancel, NULL);
g_bus_get (G_BUS_TYPE_SESSION, cancellable2, get_connection_cb_expect_success, NULL);
g_cancellable_cancel (cancellable);
g_main_loop_run (loop);
g_object_unref (cancellable);
g_object_unref (cancellable2);
session_bus_down ();
}
/* ---------------------------------------------------------------------------------------------------- */
static void
test_connection_basic (void)
{
@ -1301,6 +1365,7 @@ main (int argc,
g_test_add_func ("/gdbus/connection/signal-match-rules", test_connection_signal_match_rules);
g_test_add_func ("/gdbus/connection/filter", test_connection_filter);
g_test_add_func ("/gdbus/connection/serials", test_connection_serials);
g_test_add_func ("/gdbus/connection/cancel", test_connection_cancel);
ret = g_test_run();
g_main_loop_unref (loop);