messenger-gtk

Gtk+3 graphical user interfaces for GNUnet Messenger
Log | Files | Refs | Submodules | README | LICENSE

commit 0df8809142089441c820b27e2fd653ed0c3bc757
parent 3a3d5049bfef54bdaf33f7e184fe437d06c1a209
Author: Jacki <jacki@thejackimonster.de>
Date:   Mon, 22 Apr 2024 23:46:32 +0200

Fix deallocation issue when multiple threads accessed resources

Signed-off-by: Jacki <jacki@thejackimonster.de>

Diffstat:
Msrc/application.c | 9+++++++++
Msrc/application.h | 11+++++++++++
Msrc/chat/messenger.c | 2+-
Msrc/event.c | 57++++++++++++++++++++++++++++++++++-----------------------
Msrc/file.c | 6+++++-
Msrc/ui/accounts.c | 44++++++++++++++++++++++++++++++++------------
Msrc/ui/accounts.h | 4+++-
Msrc/ui/chat.c | 20+++++++++++++-------
Msrc/ui/media_preview.c | 34++++++++++++----------------------
Msrc/ui/media_preview.h | 2++
Msrc/ui/messenger.c | 2+-
11 files changed, 123 insertions(+), 68 deletions(-)

diff --git a/src/application.c b/src/application.c @@ -642,6 +642,15 @@ application_call_event(MESSENGER_Application *app, g_timeout_add(0, G_SOURCE_FUNC(_application_event_call), call); } +void +application_call_sync_event(MESSENGER_Application *app, + MESSENGER_ApplicationEvent event) +{ + g_assert((app) && (event)); + + event(app); +} + typedef struct MESSENGER_ApplicationMessageEventCall { MESSENGER_Application *app; diff --git a/src/application.h b/src/application.h @@ -253,6 +253,17 @@ application_call_event(MESSENGER_Application *app, MESSENGER_ApplicationEvent event); /** + * Calls a given event with the messenger application + * syncronously. + * + * @param app Messenger application + * @param event Event + */ +void +application_call_sync_event(MESSENGER_Application *app, + MESSENGER_ApplicationEvent event); + +/** * Calls a given message event with the messenger * application asyncronously but explicitly synchronized * via mutex. diff --git a/src/chat/messenger.c b/src/chat/messenger.c @@ -114,7 +114,7 @@ _chat_messenger_message(void *cls, } case GNUNET_CHAT_KIND_LOGOUT: { - application_call_event(app, event_cleanup_profile); + application_call_sync_event(app, event_cleanup_profile); break; } case GNUNET_CHAT_KIND_UPDATE: diff --git a/src/event.c b/src/event.c @@ -309,6 +309,29 @@ _iterate_profile_groups(void *cls, return GNUNET_YES; } +void +event_update_profile(MESSENGER_Application *app) +{ + g_assert(app); + + UI_MESSENGER_Handle *ui = &(app->ui.messenger); + CHAT_MESSENGER_Handle *chat = &(app->chat.messenger); + + const char *name = GNUNET_CHAT_get_name(chat->handle); + + ui_avatar_set_text(ui->profile_avatar, name); + ui_label_set_text(ui->profile_label, name); + + const char *key = GNUNET_CHAT_get_key(chat->handle); + + ui_label_set_text(ui->profile_key_label, key); + + gtk_stack_set_visible_child(ui->chats_stack, ui->no_chat_box); + + GNUNET_CHAT_iterate_contacts(chat->handle, _iterate_profile_contacts, app); + GNUNET_CHAT_iterate_groups(chat->handle, _iterate_profile_groups, app); +} + static void _clear_chat_entry(GtkWidget *widget, gpointer user_data) @@ -339,29 +362,6 @@ _clear_chat_entry(GtkWidget *widget, ui_chat_entry_dispose(entry, app); } -void -event_update_profile(MESSENGER_Application *app) -{ - g_assert(app); - - UI_MESSENGER_Handle *ui = &(app->ui.messenger); - CHAT_MESSENGER_Handle *chat = &(app->chat.messenger); - - const char *name = GNUNET_CHAT_get_name(chat->handle); - - ui_avatar_set_text(ui->profile_avatar, name); - ui_label_set_text(ui->profile_label, name); - - const char *key = GNUNET_CHAT_get_key(chat->handle); - - ui_label_set_text(ui->profile_key_label, key); - - gtk_stack_set_visible_child(ui->chats_stack, ui->no_chat_box); - - GNUNET_CHAT_iterate_contacts(chat->handle, _iterate_profile_contacts, app); - GNUNET_CHAT_iterate_groups(chat->handle, _iterate_profile_groups, app); -} - static int _cleanup_profile_contacts(void *cls, UNUSED struct GNUNET_CHAT_Handle *handle, @@ -372,6 +372,16 @@ _cleanup_profile_contacts(void *cls, return GNUNET_YES; } +static int +_cleanup_profile_files(void *cls, + UNUSED struct GNUNET_CHAT_Handle *handle, + struct GNUNET_CHAT_File *file) +{ + if (file) + file_destroy_info(file); + return GNUNET_YES; +} + void event_cleanup_profile(MESSENGER_Application *app) { @@ -388,6 +398,7 @@ event_cleanup_profile(MESSENGER_Application *app) g_list_free(entries); GNUNET_CHAT_iterate_contacts(chat->handle, _cleanup_profile_contacts, NULL); + GNUNET_CHAT_iterate_files(chat->handle, _cleanup_profile_files, NULL); } gboolean diff --git a/src/file.c b/src/file.c @@ -58,6 +58,9 @@ file_destroy_info(struct GNUNET_CHAT_File *file) if (!info) return; + if (info->preview_widgets) + g_list_free(info->preview_widgets); + file_unload_preview_image(file); if (info->update_task) @@ -115,7 +118,8 @@ file_remove_widget_from_preview(const struct GNUNET_CHAT_File *file, if (!info) return; - info->preview_widgets = g_list_remove(info->preview_widgets, widget); + if (info->preview_widgets) + info->preview_widgets = g_list_remove(info->preview_widgets, widget); if (!(info->preview_widgets)) file_unload_preview_image(file); diff --git a/src/ui/accounts.c b/src/ui/accounts.c @@ -139,11 +139,10 @@ _iterate_accounts(void *cls, g_object_set_qdata(G_OBJECT(row), app->quarks.data, account); - g_object_set_qdata_full( + g_object_set_qdata( G_OBJECT(row), app->quarks.ui, - entry, - (GDestroyNotify) ui_account_entry_delete + entry ); return GNUNET_YES; @@ -200,14 +199,11 @@ ui_accounts_dialog_init(MESSENGER_Application *app, ); } -void -ui_accounts_dialog_refresh(MESSENGER_Application *app, - UI_ACCOUNTS_Handle *handle) +static void +_ui_accounts_cleanup_listbox(UI_ACCOUNTS_Handle *handle, + MESSENGER_Application *app) { - g_assert((app) && (handle)); - - if (!(handle->accounts_listbox)) - return; + g_assert(handle); GList *list = gtk_container_get_children( GTK_CONTAINER(handle->accounts_listbox) @@ -221,6 +217,13 @@ ui_accounts_dialog_refresh(MESSENGER_Application *app, if ((!row) || (!gtk_list_box_row_get_selectable(row))) goto skip_row; + UI_ACCOUNT_ENTRY_Handle *entry = g_object_get_qdata( + G_OBJECT(row), + app->quarks.ui + ); + + ui_account_entry_delete(entry); + gtk_container_remove( GTK_CONTAINER(handle->accounts_listbox), GTK_WIDGET(row) @@ -232,6 +235,18 @@ ui_accounts_dialog_refresh(MESSENGER_Application *app, if (list) g_list_free(list); +} + +void +ui_accounts_dialog_refresh(MESSENGER_Application *app, + UI_ACCOUNTS_Handle *handle) +{ + g_assert((app) && (handle)); + + if (!(handle->accounts_listbox)) + return; + + _ui_accounts_cleanup_listbox(handle, app); GNUNET_CHAT_iterate_accounts( app->chat.messenger.handle, @@ -241,12 +256,17 @@ ui_accounts_dialog_refresh(MESSENGER_Application *app, } void -ui_accounts_dialog_cleanup(UI_ACCOUNTS_Handle *handle) +ui_accounts_dialog_cleanup(UI_ACCOUNTS_Handle *handle, + MESSENGER_Application *app) { - g_assert(handle); + g_assert((handle) && (app)); if (handle->builder) + { + _ui_accounts_cleanup_listbox(handle, app); + g_object_unref(handle->builder); + } guint show = handle->show_queued; memset(handle, 0, sizeof(*handle)); diff --git a/src/ui/accounts.h b/src/ui/accounts.h @@ -66,8 +66,10 @@ ui_accounts_dialog_refresh(MESSENGER_Application *app, * state of a given accounts dialog handle. * * @param handle Accounts dialog handle + * @param app Messenger application */ void -ui_accounts_dialog_cleanup(UI_ACCOUNTS_Handle *handle); +ui_accounts_dialog_cleanup(UI_ACCOUNTS_Handle *handle, + MESSENGER_Application *app); #endif /* UI_ACCOUNTS_H_ */ diff --git a/src/ui/chat.c b/src/ui/chat.c @@ -2036,11 +2036,10 @@ iterate_ui_chat_update_context_media(void *cls, ); g_object_set_qdata(G_OBJECT(child), closure->app->quarks.data, file); - g_object_set_qdata_full( + g_object_set_qdata( G_OBJECT(child), closure->app->quarks.ui, - handle, - (GDestroyNotify) ui_media_preview_delete + handle ); gtk_widget_set_size_request(GTK_WIDGET(child), 80, 80); @@ -2065,6 +2064,13 @@ _chat_update_media(UI_CHAT_Handle *handle, GtkWidget *widget = GTK_WIDGET(item->data); item = item->next; + UI_MEDIA_PREVIEW_Handle *media = g_object_get_qdata( + G_OBJECT(widget), + app->quarks.ui + ); + + ui_media_preview_delete(media); + gtk_container_remove( GTK_CONTAINER(handle->chat_media_flowbox), widget @@ -2289,12 +2295,12 @@ ui_chat_delete(UI_CHAT_Handle *handle) ui_picker_delete(handle->picker); - if (handle->loads) - g_list_free_full(handle->loads, (GDestroyNotify) ui_file_load_entry_delete); - _chat_update_contacts(handle, handle->app, NULL); - _chat_update_files(handle, handle->app, NULL); _chat_update_media(handle, handle->app, NULL); + _chat_update_files(handle, handle->app, NULL); + + if (handle->loads) + g_list_free_full(handle->loads, (GDestroyNotify) ui_file_load_entry_delete); g_object_unref(handle->builder); diff --git a/src/ui/media_preview.c b/src/ui/media_preview.c @@ -117,6 +117,8 @@ ui_media_preview_new(MESSENGER_Application *app) UI_MEDIA_PREVIEW_Handle* handle = g_malloc(sizeof(UI_MEDIA_PREVIEW_Handle)); + handle->file = NULL; + handle->builder = ui_builder_from_resource( application_get_resource_path(app, "ui/media_preview.ui") ); @@ -145,24 +147,18 @@ void ui_media_preview_update(UI_MEDIA_PREVIEW_Handle *handle, struct GNUNET_CHAT_File *file) { - g_assert((handle) && (file)); - - struct GNUNET_CHAT_File *previous = (struct GNUNET_CHAT_File *) g_object_get_qdata( - G_OBJECT(handle->preview_drawing_area), - handle->app->quarks.data - ); + g_assert(handle); - if (previous) - file_remove_widget_from_preview(previous, GTK_WIDGET(handle->preview_drawing_area)); + if (handle->file) + file_remove_widget_from_preview(handle->file, GTK_WIDGET(handle->preview_drawing_area)); - file_load_preview_image(file); - file_add_widget_to_preview(file, GTK_WIDGET(handle->preview_drawing_area)); + if (file) + { + file_load_preview_image(file); + file_add_widget_to_preview(file, GTK_WIDGET(handle->preview_drawing_area)); + } - g_object_set_qdata( - G_OBJECT(handle->preview_drawing_area), - handle->app->quarks.data, - file - ); + handle->file = file; } void @@ -170,13 +166,7 @@ ui_media_preview_delete(UI_MEDIA_PREVIEW_Handle *handle) { g_assert(handle); - struct GNUNET_CHAT_File *file = (struct GNUNET_CHAT_File *) g_object_get_qdata( - G_OBJECT(handle->preview_drawing_area), - handle->app->quarks.data - ); - - if (file) - file_remove_widget_from_preview(file, GTK_WIDGET(handle->preview_drawing_area)); + ui_media_preview_update(handle, NULL); g_object_unref(handle->builder); diff --git a/src/ui/media_preview.h b/src/ui/media_preview.h @@ -31,6 +31,8 @@ typedef struct UI_MEDIA_PREVIEW_Handle { + const struct GNUNET_CHAT_File *file; + GtkBuilder *builder; GtkWidget *media_box; diff --git a/src/ui/messenger.c b/src/ui/messenger.c @@ -387,7 +387,7 @@ handle_main_window_destroy(UNUSED GtkWidget *window, #endif ui_messenger_cleanup(&(app->ui.messenger)); - ui_accounts_dialog_cleanup(&(app->ui.accounts)); + ui_accounts_dialog_cleanup(&(app->ui.accounts), app); application_exit(app, MESSENGER_QUIT); }