From aaeebd3fe9f338873fa4d4bc8c38b3af753b328b Mon Sep 17 00:00:00 2001 From: WerWolv Date: Fri, 12 May 2023 15:46:13 +0200 Subject: [PATCH] fix: Various pattern execution race conditions --- .../include/hex/api/content_registry.hpp | 2 +- lib/libimhex/source/api/content_registry.cpp | 4 +- .../source/content/data_processor_nodes.cpp | 2 +- .../content/views/view_pattern_data.cpp | 2 +- .../content/views/view_pattern_editor.cpp | 75 ++++++++++--------- 5 files changed, 45 insertions(+), 40 deletions(-) diff --git a/lib/libimhex/include/hex/api/content_registry.hpp b/lib/libimhex/include/hex/api/content_registry.hpp index b1b0da6e5..a54606312 100644 --- a/lib/libimhex/include/hex/api/content_registry.hpp +++ b/lib/libimhex/include/hex/api/content_registry.hpp @@ -272,7 +272,7 @@ namespace hex { * @brief Provides access to the current provider's pattern language runtime's lock * @return Lock */ - std::scoped_lock getRuntimeLock(); + std::mutex& getRuntimeLock(); /** * @brief Configures the pattern language runtime using ImHex's default settings diff --git a/lib/libimhex/source/api/content_registry.cpp b/lib/libimhex/source/api/content_registry.cpp index 6d01d81f3..8da050bf5 100644 --- a/lib/libimhex/source/api/content_registry.cpp +++ b/lib/libimhex/source/api/content_registry.cpp @@ -265,10 +265,10 @@ namespace hex { return *runtime; } - std::scoped_lock getRuntimeLock() { + std::mutex& getRuntimeLock() { static std::mutex runtimeLock; - return std::scoped_lock(runtimeLock); + return runtimeLock; } void configureRuntime(pl::PatternLanguage &runtime, prv::Provider *provider) { diff --git a/plugins/builtin/source/content/data_processor_nodes.cpp b/plugins/builtin/source/content/data_processor_nodes.cpp index 3c4c58d75..52f4269a7 100644 --- a/plugins/builtin/source/content/data_processor_nodes.cpp +++ b/plugins/builtin/source/content/data_processor_nodes.cpp @@ -1162,7 +1162,7 @@ namespace hex::plugin::builtin { } void process() override { - auto lock = ContentRegistry::PatternLanguage::getRuntimeLock(); + auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock()); auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); const auto &outVars = runtime.getOutVariables(); diff --git a/plugins/builtin/source/content/views/view_pattern_data.cpp b/plugins/builtin/source/content/views/view_pattern_data.cpp index 5c3821107..3878290cb 100644 --- a/plugins/builtin/source/content/views/view_pattern_data.cpp +++ b/plugins/builtin/source/content/views/view_pattern_data.cpp @@ -37,7 +37,7 @@ namespace hex::plugin::builtin { if (!runtime.arePatternsValid()) { this->m_patternDrawer.draw({}); } else { - auto lock = ContentRegistry::PatternLanguage::getRuntimeLock(); + auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock()); if (this->m_shouldReset) { this->m_patternDrawer.reset(); diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index 40fd15976..63cecd238 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -141,36 +141,39 @@ namespace hex::plugin::builtin { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1); - auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); - if (runtime.isRunning()) { - if (ImGui::IconButton(ICON_VS_DEBUG_STOP, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) - runtime.abort(); - } else { - if (ImGui::IconButton(ICON_VS_DEBUG_START, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen)) || this->m_triggerEvaluation) { - this->m_triggerEvaluation = false; - this->evaluatePattern(this->m_textEditor.GetText(), provider); - } - } - - - ImGui::PopStyleVar(); - - ImGui::SameLine(); - if (this->m_runningEvaluators > 0) - ImGui::TextSpinner("hex.builtin.view.pattern_editor.evaluating"_lang); - else { - if (ImGui::Checkbox("hex.builtin.view.pattern_editor.auto"_lang, &this->m_runAutomatically)) { - if (this->m_runAutomatically) - this->m_hasUnevaluatedChanges = true; + { + auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock()); + auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); + if (runtime.isRunning()) { + if (ImGui::IconButton(ICON_VS_DEBUG_STOP, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) + runtime.abort(); + } else { + if (ImGui::IconButton(ICON_VS_DEBUG_START, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen)) || this->m_triggerEvaluation) { + this->m_triggerEvaluation = false; + this->evaluatePattern(this->m_textEditor.GetText(), provider); + } } - ImGui::SameLine(); - ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical); - ImGui::SameLine(); - ImGui::TextFormatted("{} / {}", - runtime.getCreatedPatternCount(), - runtime.getMaximumPatternCount()); + ImGui::PopStyleVar(); + + ImGui::SameLine(); + if (this->m_runningEvaluators > 0) + ImGui::TextSpinner("hex.builtin.view.pattern_editor.evaluating"_lang); + else { + if (ImGui::Checkbox("hex.builtin.view.pattern_editor.auto"_lang, &this->m_runAutomatically)) { + if (this->m_runAutomatically) + this->m_hasUnevaluatedChanges = true; + } + + ImGui::SameLine(); + ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical); + ImGui::SameLine(); + + ImGui::TextFormatted("{} / {}", + runtime.getCreatedPatternCount(), + runtime.getMaximumPatternCount()); + } } if (this->m_textEditor.IsTextChanged()) { @@ -407,6 +410,7 @@ namespace hex::plugin::builtin { } void ViewPatternEditor::drawSectionSelector(ImVec2 size, std::map §ions) { + auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock()); auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); if (ImGui::BeginTable("##sections_table", 3, ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, size)) { @@ -640,6 +644,8 @@ namespace hex::plugin::builtin { } void ViewPatternEditor::evaluatePattern(const std::string &code, prv::Provider *provider) { + auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock()); + this->m_runningEvaluators++; *this->m_executionDone = false; @@ -650,11 +656,11 @@ namespace hex::plugin::builtin { EventManager::post(); - auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); - ContentRegistry::PatternLanguage::configureRuntime(runtime, provider); + TaskManager::createTask("hex.builtin.view.pattern_editor.evaluating", TaskManager::NoProgress, [this, code, provider](auto &task) { + auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock()); - TaskManager::createTask("hex.builtin.view.pattern_editor.evaluating", TaskManager::NoProgress, [this, code, &runtime](auto &task) { - auto lock = ContentRegistry::PatternLanguage::getRuntimeLock(); + auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); + ContentRegistry::PatternLanguage::configureRuntime(runtime, provider); task.setInterruptCallback([&runtime] { runtime.abort(); }); @@ -725,9 +731,6 @@ namespace hex::plugin::builtin { }); EventManager::subscribe(this, [this](prv::Provider *provider) { - auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); - ContentRegistry::PatternLanguage::configureRuntime(runtime, provider); - TaskManager::createBackgroundTask("Analyzing file content", [this, provider](auto &) { if (!this->m_autoLoadPatterns) return; @@ -737,7 +740,7 @@ namespace hex::plugin::builtin { *this->m_sourceCode = this->m_textEditor.GetText(); } - auto lock = ContentRegistry::PatternLanguage::getRuntimeLock(); + auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock()); auto& runtime = ContentRegistry::PatternLanguage::getRuntime(); ContentRegistry::PatternLanguage::configureRuntime(runtime, provider); @@ -939,6 +942,7 @@ namespace hex::plugin::builtin { if (this->m_runningEvaluators != 0) return std::nullopt; + auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock()); auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); std::optional color; @@ -958,6 +962,7 @@ namespace hex::plugin::builtin { ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) { hex::unused(data, size); + auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock()); auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); auto patterns = runtime.getPatternsAtAddress(address);