From 723b3ff838ce9312ce03fe91c9561a44900988fc Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 16 Nov 2022 13:33:06 -0800 Subject: [PATCH] Made responses to platform methods threadsafe in linux --- shell/platform/linux/fl_binary_messenger.cc | 48 ++++++++------------- shell/platform/linux/fl_engine.cc | 1 + 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/shell/platform/linux/fl_binary_messenger.cc b/shell/platform/linux/fl_binary_messenger.cc index 92c3f69dc29e2..2353c2aeedcc2 100644 --- a/shell/platform/linux/fl_binary_messenger.cc +++ b/shell/platform/linux/fl_binary_messenger.cc @@ -33,7 +33,7 @@ G_DEFINE_INTERFACE(FlBinaryMessenger, fl_binary_messenger, G_TYPE_OBJECT) struct _FlBinaryMessengerImpl { GObject parent_instance; - FlEngine* engine; + GWeakRef engine; // PlatformMessageHandler keyed by channel name. GHashTable* platform_message_handlers; @@ -81,7 +81,9 @@ static void fl_binary_messenger_response_handle_impl_dispose(GObject* object) { FlBinaryMessengerResponseHandleImpl* self = FL_BINARY_MESSENGER_RESPONSE_HANDLE_IMPL(object); - if (self->response_handle != nullptr && self->messenger->engine != nullptr) { + g_autoptr(FlEngine) engine = + FL_ENGINE(g_weak_ref_get(&self->messenger->engine)); + if (self->response_handle != nullptr && engine != nullptr) { g_critical("FlBinaryMessengerResponseHandle was not responded to"); } @@ -141,19 +143,6 @@ static void platform_message_handler_free(gpointer data) { g_free(self); } -static void engine_weak_notify_cb(gpointer user_data, - GObject* where_the_object_was) { - FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(user_data); - self->engine = nullptr; - - // Disconnect any handlers. - // Take the reference in case a handler tries to modify this table. - g_autoptr(GHashTable) handlers = self->platform_message_handlers; - self->platform_message_handlers = g_hash_table_new_full( - g_str_hash, g_str_equal, g_free, platform_message_handler_free); - g_hash_table_remove_all(handlers); -} - static gboolean fl_binary_messenger_platform_message_cb( FlEngine* engine, const gchar* channel, @@ -179,11 +168,7 @@ static gboolean fl_binary_messenger_platform_message_cb( static void fl_binary_messenger_impl_dispose(GObject* object) { FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(object); - - if (self->engine != nullptr) { - g_object_weak_unref(G_OBJECT(self->engine), engine_weak_notify_cb, self); - self->engine = nullptr; - } + g_weak_ref_clear(&self->engine); g_clear_pointer(&self->platform_message_handlers, g_hash_table_unref); @@ -199,7 +184,8 @@ static void set_message_handler_on_channel( FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(messenger); // Don't set handlers if engine already gone. - if (self->engine == nullptr) { + g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine)); + if (engine == nullptr) { if (handler != nullptr) { g_warning( "Attempted to set message handler on an FlBinaryMessenger without an " @@ -220,6 +206,7 @@ static void set_message_handler_on_channel( } } +// Note: This function can be called from any thread. static gboolean send_response(FlBinaryMessenger* messenger, FlBinaryMessengerResponseHandle* response_handle_, GBytes* response, @@ -233,7 +220,8 @@ static gboolean send_response(FlBinaryMessenger* messenger, g_return_val_if_fail(response_handle->messenger == self, FALSE); g_return_val_if_fail(response_handle->response_handle != nullptr, FALSE); - if (self->engine == nullptr) { + g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine)); + if (engine == nullptr) { return TRUE; } @@ -246,7 +234,7 @@ static gboolean send_response(FlBinaryMessenger* messenger, } gboolean result = fl_engine_send_platform_message_response( - self->engine, response_handle->response_handle, response, error); + engine, response_handle->response_handle, response, error); response_handle->response_handle = nullptr; return result; @@ -267,12 +255,13 @@ static void send_on_channel(FlBinaryMessenger* messenger, gpointer user_data) { FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(messenger); - if (self->engine == nullptr) { + g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine)); + if (engine == nullptr) { return; } fl_engine_send_platform_message( - self->engine, channel, message, cancellable, + engine, channel, message, cancellable, callback != nullptr ? platform_message_ready_cb : nullptr, callback != nullptr ? g_task_new(self, cancellable, callback, user_data) : nullptr); @@ -287,11 +276,12 @@ static GBytes* send_on_channel_finish(FlBinaryMessenger* messenger, g_autoptr(GTask) task = G_TASK(result); GAsyncResult* r = G_ASYNC_RESULT(g_task_propagate_pointer(task, nullptr)); - if (self->engine == nullptr) { + g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine)); + if (engine == nullptr) { return nullptr; } - return fl_engine_send_platform_message_finish(self->engine, r, error); + return fl_engine_send_platform_message_finish(engine, r, error); } static void fl_binary_messenger_impl_class_init( @@ -321,8 +311,7 @@ FlBinaryMessenger* fl_binary_messenger_new(FlEngine* engine) { // Added to stop compiler complaining about an unused function. FL_IS_BINARY_MESSENGER_IMPL(self); - self->engine = engine; - g_object_weak_ref(G_OBJECT(engine), engine_weak_notify_cb, self); + g_weak_ref_init(&self->engine, G_OBJECT(engine)); fl_engine_set_platform_message_handler( engine, fl_binary_messenger_platform_message_cb, self, NULL); @@ -343,6 +332,7 @@ G_MODULE_EXPORT void fl_binary_messenger_set_message_handler_on_channel( self, channel, handler, user_data, destroy_notify); } +// Note: This function can be called from any thread. G_MODULE_EXPORT gboolean fl_binary_messenger_send_response( FlBinaryMessenger* self, FlBinaryMessengerResponseHandle* response_handle, diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index 042e91abc4b1b..896eef701fc8e 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -616,6 +616,7 @@ void fl_engine_set_on_pre_engine_restart_handler( self->on_pre_engine_restart_handler_destroy_notify = destroy_notify; } +// Note: This function can be called from any thread. gboolean fl_engine_send_platform_message_response( FlEngine* self, const FlutterPlatformMessageResponseHandle* handle,