From 0d4b8bacce933e34a41769b1051b25f82f922201 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 5 Feb 2021 05:18:31 +0100 Subject: Matrix: fix crash when a room is being removed in one thread and the room description is set in another, at the same time --- plugins/Matrix.hpp | 2 +- src/QuickMedia.cpp | 15 +++++++-------- src/plugins/Matrix.cpp | 16 ++++++++-------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp index be89adb..df8fa43 100644 --- a/plugins/Matrix.hpp +++ b/plugins/Matrix.hpp @@ -136,7 +136,7 @@ namespace QuickMedia { bool last_message_read = true; bool users_fetched = false; time_t last_read_message_timestamp = 0; - void *userdata = nullptr; // Pointer to BodyItem. Note: this has to be valid as long as the room is valid + std::shared_ptr body_item; // These are messages fetched with |Matrix::get_message_by_id|. Needed to show replies, when replying to old message not part of /sync. // The value is nullptr if the message is fetched and cached but the event if referenced an invalid message. diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 719345d..76bd084 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -3440,7 +3440,7 @@ namespace QuickMedia { process_pinned_events(std::move(pinned_events)); tabs[PINNED_TAB_INDEX].body->select_last_item(); - room_name_text.setString(static_cast(current_room->userdata)->get_title()); + room_name_text.setString(current_room->body_item->get_title()); room_avatar_thumbnail_data = std::make_shared(); read_marker_timeout_ms = 0; @@ -4429,8 +4429,8 @@ namespace QuickMedia { typing_state_queue.push(false); } - if(current_room && current_room->userdata && room_avatar_thumbnail_data->loading_state == LoadingState::NOT_LOADED) - AsyncImageLoader::get_instance().load_thumbnail(static_cast(current_room->userdata)->thumbnail_url, false, sf::Vector2i(32, 32), use_tor, room_avatar_thumbnail_data); + if(current_room && current_room->body_item && room_avatar_thumbnail_data->loading_state == LoadingState::NOT_LOADED) + AsyncImageLoader::get_instance().load_thumbnail(current_room->body_item->thumbnail_url, false, sf::Vector2i(32, 32), use_tor, room_avatar_thumbnail_data); if(room_avatar_thumbnail_data->loading_state == LoadingState::FINISHED_LOADING && room_avatar_thumbnail_data->image->getSize().x > 0 && room_avatar_thumbnail_data->image->getSize().y > 0) { if(!room_avatar_thumbnail_data->texture.loadFromImage(*room_avatar_thumbnail_data->image)) @@ -4686,10 +4686,9 @@ namespace QuickMedia { tabs[MESSAGES_TAB_INDEX].body->draw_item(window, currently_operating_on_item.get(), body_item_pos, body_item_size); } - if(selected_tab == MESSAGES_TAB_INDEX && current_room && current_room->userdata && !current_room->last_message_read) { + if(selected_tab == MESSAGES_TAB_INDEX && current_room && current_room->body_item && !current_room->last_message_read) { if(tabs[selected_tab].body->is_last_item_fully_visible()) { - BodyItem *current_room_body_item = static_cast(current_room->userdata); - std::string room_desc = current_room_body_item->get_description(); + std::string room_desc = current_room->body_item->get_description(); if(strncmp(room_desc.c_str(), "Unread: ", 8) == 0) room_desc = room_desc.substr(8); size_t last_line_start = room_desc.rfind('\n'); @@ -4699,9 +4698,9 @@ namespace QuickMedia { if(last_line_size >= 23 && memcmp(&room_desc[last_line_start], "** ", 3) == 0 && memcmp(&room_desc[room_desc.size() - 20], "unread mention(s) **", 20) == 0) room_desc.erase(room_desc.begin() + last_line_start - 1, room_desc.end()); } - current_room_body_item->set_description(std::move(room_desc)); + current_room->body_item->set_description(std::move(room_desc)); // TODO: Show a line like nheko instead for unread messages, or something else - current_room_body_item->set_title_color(sf::Color::White); + current_room->body_item->set_title_color(sf::Color::White); current_room->last_message_read = true; // TODO: Maybe set this instead when the mention is visible on the screen? current_room->unread_notification_count = 0; diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index ba8533b..3a2c02c 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -296,6 +296,8 @@ namespace QuickMedia { //message_by_event_id.clear(); pinned_events.clear(); tags.clear(); + // TODO: Do this? what if its being used in another thread? + //body_item.reset(); } MatrixQuickMedia::MatrixQuickMedia(Program *program, Matrix *matrix, MatrixRoomsPage *rooms_page, MatrixRoomTagsPage *room_tags_page, MatrixInvitesPage *invites_page) : @@ -317,7 +319,7 @@ namespace QuickMedia { body_item->userdata = room; // Note: this has to be valid as long as the room list is valid! body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; body_item->thumbnail_size = sf::Vector2i(32, 32); - room->userdata = body_item.get(); + room->body_item = body_item; rooms_page->add_body_item(body_item); room_body_item_by_room[room] = body_item; } @@ -484,9 +486,8 @@ namespace QuickMedia { if(last_new_message->timestamp > read_marker_message_timestamp) last_unread_message = last_new_message.get(); - BodyItem *room_body_item = static_cast(room->userdata); //assert(room_body_item); - if(!room_body_item) + if(!room->body_item) return; if(last_unread_message && !sync_is_cache) { @@ -494,14 +495,14 @@ namespace QuickMedia { int unread_notification_count = room->unread_notification_count; if(unread_notification_count > 0) room_desc += "\n** " + std::to_string(unread_notification_count) + " unread mention(s) **"; // TODO: Better notification? - room_body_item->set_description(std::move(room_desc)); - room_body_item->set_title_color(sf::Color(255, 100, 100)); + room->body_item->set_description(std::move(room_desc)); + room->body_item->set_title_color(sf::Color(255, 100, 100)); room->last_message_read = false; rooms_page->move_room_to_top(room); room_tags_page->move_room_to_top(room); } else if(is_initial_sync) { - room_body_item->set_description(matrix->message_get_author_displayname(last_new_message.get()) + ": " + message_to_room_description_text(last_new_message.get())); + room->body_item->set_description(matrix->message_get_author_displayname(last_new_message.get()) + ": " + message_to_room_description_text(last_new_message.get())); } } @@ -608,8 +609,7 @@ namespace QuickMedia { // TODO: Optimize with hash map instead of linear search? or cache the index std::lock_guard lock(mutex); #if 1 - BodyItem *room_body_item = static_cast(room->userdata); - int room_body_index = body->get_index_by_body_item(room_body_item); + int room_body_index = body->get_index_by_body_item(room->body_item.get()); if(room_body_index != -1) { std::shared_ptr body_item = body->items[room_body_index]; int body_swap_index = -1; -- cgit v1.2.3