From 4b8e2752540985f462761d9a7696c9c362596294 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Tue, 27 Dec 2022 11:35:20 +0100 Subject: [PATCH] fix: Crash when closing providers too quickly --- lib/libimhex/include/hex/api/task.hpp | 4 +++ lib/libimhex/include/hex/helpers/magic.hpp | 4 +-- lib/libimhex/source/api/imhex_api.cpp | 4 ++- lib/libimhex/source/api/task.cpp | 25 ++++++++++++++++++- .../content/views/view_pattern_editor.cpp | 3 ++- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/lib/libimhex/include/hex/api/task.hpp b/lib/libimhex/include/hex/api/task.hpp index bad80eb01..3eb7285e2 100644 --- a/lib/libimhex/include/hex/api/task.hpp +++ b/lib/libimhex/include/hex/api/task.hpp @@ -102,16 +102,20 @@ namespace hex { static void collectGarbage(); static size_t getRunningTaskCount(); + static size_t getRunningBackgroundTaskCount(); static std::list> &getRunningTasks(); static void doLater(const std::function &function); static void runDeferredCalls(); + + static void runWhenTasksFinished(const std::function &function); private: static std::mutex s_deferredCallsMutex; static std::list> s_tasks; static std::list> s_taskQueue; static std::list> s_deferredCalls; + static std::list> s_tasksFinishedCallbacks; static std::mutex s_queueMutex; static std::condition_variable s_jobCondVar; diff --git a/lib/libimhex/include/hex/helpers/magic.hpp b/lib/libimhex/include/hex/helpers/magic.hpp index c54235e15..0450b212c 100644 --- a/lib/libimhex/include/hex/helpers/magic.hpp +++ b/lib/libimhex/include/hex/helpers/magic.hpp @@ -17,8 +17,8 @@ namespace hex::magic { bool compile(); std::string getDescription(const std::vector &data); - std::string getDescription(prv::Provider *provider, size_t size = 5_MiB); + std::string getDescription(prv::Provider *provider, size_t size = 100_KiB); std::string getMIMEType(const std::vector &data); - std::string getMIMEType(prv::Provider *provider, size_t size = 5_MiB); + std::string getMIMEType(prv::Provider *provider, size_t size = 100_KiB); } \ No newline at end of file diff --git a/lib/libimhex/source/api/imhex_api.cpp b/lib/libimhex/source/api/imhex_api.cpp index a8e0ccfea..0704f806d 100644 --- a/lib/libimhex/source/api/imhex_api.cpp +++ b/lib/libimhex/source/api/imhex_api.cpp @@ -322,7 +322,9 @@ namespace hex { provider->close(); EventManager::post(provider); - delete provider; + TaskManager::runWhenTasksFinished([provider] { + delete provider; + }); } prv::Provider* createProvider(const std::string &unlocalizedName, bool skipLoadInterface) { diff --git a/lib/libimhex/source/api/task.cpp b/lib/libimhex/source/api/task.cpp index 7d0c07cd1..3d208a5de 100644 --- a/lib/libimhex/source/api/task.cpp +++ b/lib/libimhex/source/api/task.cpp @@ -12,6 +12,7 @@ namespace hex { std::list> TaskManager::s_tasks, TaskManager::s_taskQueue; std::list> TaskManager::s_deferredCalls; + std::list> TaskManager::s_tasksFinishedCallbacks; std::mutex TaskManager::s_queueMutex; std::condition_variable TaskManager::s_jobCondVar; @@ -238,8 +239,16 @@ namespace hex { } void TaskManager::collectGarbage() { - std::unique_lock lock(s_queueMutex); + std::unique_lock lock1(s_queueMutex); + std::unique_lock lock2(s_deferredCallsMutex); + std::erase_if(s_tasks, [](const auto &task) { return task->isFinished() && !task->hadException(); }); + + if (s_tasks.empty()) { + for (auto &call : s_tasksFinishedCallbacks) + call(); + s_tasksFinishedCallbacks.clear(); + } } std::list> &TaskManager::getRunningTasks() { @@ -254,6 +263,14 @@ namespace hex { }); } + size_t TaskManager::getRunningBackgroundTaskCount() { + std::unique_lock lock(s_queueMutex); + + return std::count_if(s_tasks.begin(), s_tasks.end(), [](const auto &task){ + return task->isBackgroundTask(); + }); + } + void TaskManager::doLater(const std::function &function) { std::scoped_lock lock(s_deferredCallsMutex); @@ -270,4 +287,10 @@ namespace hex { s_deferredCalls.clear(); } + void TaskManager::runWhenTasksFinished(const std::function &function) { + std::scoped_lock lock(s_deferredCallsMutex); + + s_tasksFinishedCallbacks.push_back(function); + } + } \ No newline at end of file diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index 0a7771d0c..2e36a5183 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -225,7 +225,8 @@ namespace hex::plugin::builtin { while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { - const auto &[level, message] = console[i]; + auto [level, message] = console[i]; + std::replace_if(message.begin(), message.end(), [](char c) { return !std::isprint(c); }, ' '); switch (level) { using enum pl::core::LogConsole::Level;