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:
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);
}