feat: Added basic ability to interrupt long running tasks

This commit is contained in:
WerWolv
2022-08-17 16:15:36 +02:00
parent cf6ae52889
commit e779285be4
26 changed files with 422 additions and 310 deletions

View File

@@ -14,7 +14,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.help", 1000, [&, this] {
if (ImGui::MenuItem("hex.builtin.view.help.about.name"_lang, "")) {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.help.about.name").c_str()); });
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.help.about.name").c_str()); });
this->m_aboutWindowOpen = true;
this->getWindowOpenState() = true;
}

View File

@@ -24,9 +24,8 @@ namespace hex::plugin::builtin {
void ViewDisassembler::disassemble() {
this->m_disassembly.clear();
this->m_disassembling = true;
std::thread([this] {
this->m_disassemblerTask = TaskManager::createTask("hex.builtin.view.disassembler.disassembling", this->m_codeRegion.getSize(), [this](auto &task) {
csh capstoneHandle;
cs_insn *instructions = nullptr;
@@ -40,7 +39,6 @@ namespace hex::plugin::builtin {
std::vector<u8> buffer(2048, 0x00);
size_t size = this->m_codeRegion.getSize();
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.disassembler.disassembling", size);
for (u64 address = 0; address < size; address += 2048) {
task.update(address);
@@ -80,9 +78,7 @@ namespace hex::plugin::builtin {
cs_close(&capstoneHandle);
}
this->m_disassembling = false;
}).detach();
});
}
void ViewDisassembler::drawContent() {
@@ -321,14 +317,14 @@ namespace hex::plugin::builtin {
}
ImGui::EndChild();
ImGui::BeginDisabled(this->m_disassembling);
ImGui::BeginDisabled(this->m_disassemblerTask.isRunning());
{
if (ImGui::Button("hex.builtin.view.disassembler.disassemble"_lang))
this->disassemble();
}
ImGui::EndDisabled();
if (this->m_disassembling) {
if (this->m_disassemblerTask.isRunning()) {
ImGui::SameLine();
ImGui::TextSpinner("hex.builtin.view.disassembler.disassembling"_lang);
}
@@ -345,7 +341,7 @@ namespace hex::plugin::builtin {
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.bytes"_lang);
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.title"_lang);
if (!this->m_disassembling) {
if (!this->m_disassemblerTask.isRunning()) {
ImGuiListClipper clipper;
clipper.Begin(this->m_disassembly.size());

View File

@@ -6,7 +6,6 @@
#include <array>
#include <regex>
#include <string>
#include <thread>
#include <utility>
#include <llvm/Demangle/Demangle.h>
@@ -319,9 +318,7 @@ namespace hex::plugin::builtin {
}
}();
this->m_searchRunning = true;
std::thread([this, settings = this->m_searchSettings, searchRegion]{
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.find.searching", searchRegion.getSize());
this->m_searchTask = TaskManager::createTask("hex.builtin.view.find.searching", searchRegion.getSize(), [this, settings = this->m_searchSettings, searchRegion](auto &task) {
auto provider = ImHexApi::Provider::get();
switch (settings.mode) {
@@ -338,7 +335,7 @@ namespace hex::plugin::builtin {
case BinaryPattern:
this->m_foundOccurrences[provider] = searchBinaryPattern(task, provider, searchRegion, settings.binaryPattern);
break;
}
}
this->m_sortedOccurrences[provider] = this->m_foundOccurrences[provider];
@@ -346,9 +343,7 @@ namespace hex::plugin::builtin {
for (const auto &occurrence : this->m_foundOccurrences[provider])
intervals.push_back(OccurrenceTree::interval(occurrence.region.getStartAddress(), occurrence.region.getEndAddress(), occurrence));
this->m_occurrenceTree[provider] = std::move(intervals);
this->m_searchRunning = false;
}).detach();
});
}
std::string ViewFind::decodeValue(prv::Provider *provider, Occurrence occurrence) const {
@@ -408,7 +403,7 @@ namespace hex::plugin::builtin {
if (ImGui::Begin(View::toWindowName("hex.builtin.view.find.name").c_str(), &this->getWindowOpenState())) {
auto provider = ImHexApi::Provider::get();
ImGui::BeginDisabled(this->m_searchRunning);
ImGui::BeginDisabled(this->m_searchTask.isRunning());
{
ui::regionSelectionPicker(&this->m_searchSettings.range, true, true);

View File

@@ -189,13 +189,10 @@ namespace hex::plugin::builtin {
ImGui::EndTabBar();
}
if (!this->m_searchRunning && !searchSequence.empty() && this->m_shouldSearch) {
this->m_searchRunning = true;
std::thread([this, searchSequence, editor]{
auto task = ImHexApi::Tasks::createTask("Searching", ImHexApi::Provider::get()->getSize());
if (!this->m_searchTask.isRunning() && !searchSequence.empty() && this->m_shouldSearch) {
this->m_searchTask = TaskManager::createTask("hex.builtin.common.processing", ImHexApi::Provider::get()->getActualSize(), [this, editor, searchSequence](auto &) {
if (auto region = this->findSequence(editor, searchSequence, this->m_backwards); region.has_value()) {
ImHexApi::Tasks::doLater([editor, region]{
TaskManager::doLater([editor, region]{
editor->setSelection(region->getStartAddress(), region->getEndAddress());
editor->jumpToSelection();
});
@@ -203,8 +200,7 @@ namespace hex::plugin::builtin {
this->m_shouldSearch = false;
this->m_requestFocus = true;
this->m_searchRunning = false;
}).detach();
});
}
}
@@ -218,7 +214,7 @@ namespace hex::plugin::builtin {
this->m_requestFocus = false;
}
ImGui::BeginDisabled(this->m_searchRunning);
ImGui::BeginDisabled(this->m_searchTask.isRunning());
{
ImGui::SameLine();
if (ImGui::IconButton(ICON_VS_SEARCH "##search", ButtonColor, ButtonSize)) {
@@ -285,7 +281,7 @@ namespace hex::plugin::builtin {
std::atomic<bool> m_shouldSearch = false;
std::atomic<bool> m_backwards = false;
std::atomic<bool> m_searchRunning = false;
TaskHolder m_searchTask;
};
class PopupBaseAddress : public ViewHexEditor::Popup {

View File

@@ -4,20 +4,15 @@
#include <hex/providers/provider.hpp>
#include <hex/providers/buffered_reader.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/literals.hpp>
#include <hex/helpers/magic.hpp>
#include <cstring>
#include <cmath>
#include <cinttypes>
#include <filesystem>
#include <numeric>
#include <span>
#include <thread>
#include <vector>
#include <hex/helpers/magic.hpp>
#include <implot.h>
@@ -80,12 +75,10 @@ namespace hex::plugin::builtin {
}
void ViewInformation::analyze() {
this->m_analyzing = true;
std::thread([this] {
this->m_analyzerTask = TaskManager::createTask("hex.builtin.view.information.analyzing", 0, [this](auto &task) {
auto provider = ImHexApi::Provider::get();
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.information.analyzing", provider->getActualSize());
task.setMaxValue(provider->getActualSize());
this->m_analyzedRegion = { provider->getBaseAddress(), provider->getBaseAddress() + provider->getSize() };
@@ -127,9 +120,7 @@ namespace hex::plugin::builtin {
else
this->m_highestBlockEntropy = 0;
}
this->m_analyzing = false;
}).detach();
});
}
void ViewInformation::drawContent() {
@@ -138,14 +129,14 @@ namespace hex::plugin::builtin {
auto provider = ImHexApi::Provider::get();
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
ImGui::BeginDisabled(this->m_analyzing);
ImGui::BeginDisabled(this->m_analyzerTask.isRunning());
{
if (ImGui::Button("hex.builtin.view.information.analyze"_lang, ImVec2(ImGui::GetContentRegionAvail().x, 0)))
this->analyze();
}
ImGui::EndDisabled();
if (this->m_analyzing) {
if (this->m_analyzerTask.isRunning()) {
ImGui::TextSpinner("hex.builtin.view.information.analyzing"_lang);
} else {
ImGui::NewLine();

View File

@@ -815,10 +815,7 @@ namespace hex::plugin::builtin {
EventManager::post<EventHighlightingChanged>();
std::thread([this, code, &runtime] {
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.pattern_editor.evaluating", 1);
TaskManager::createTask("hex.builtin.view.pattern_editor.evaluating", TaskManager::NoProgress, [this, &runtime, code](auto &) {
std::map<std::string, pl::core::Token::Literal> envVars;
for (const auto &[id, name, value, type] : this->m_envVarEntries)
envVars.insert({ name, value });
@@ -851,7 +848,7 @@ namespace hex::plugin::builtin {
this->m_runningEvaluators--;
this->m_lastEvaluationProcessed = false;
}).detach();
});
}
}

View File

@@ -11,14 +11,14 @@ namespace hex::plugin::builtin {
ViewSettings::ViewSettings() : View("hex.builtin.view.settings.name") {
EventManager::subscribe<RequestOpenWindow>(this, [this](const std::string &name) {
if (name == "Settings") {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
this->getWindowOpenState() = true;
}
});
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.help", 2000, [&, this] {
if (ImGui::MenuItem("hex.builtin.view.settings.name"_lang)) {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
this->getWindowOpenState() = true;
}
});

View File

@@ -29,7 +29,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.help", 3000, [&, this] {
if (ImGui::MenuItem("hex.builtin.view.store.name"_lang)) {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); });
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); });
this->getWindowOpenState() = true;
}
});

View File

@@ -44,7 +44,7 @@ namespace hex::plugin::builtin {
if (ImGui::Button("hex.builtin.view.yara.reload"_lang)) this->reloadRules();
} else {
ImGui::BeginDisabled(this->m_matching);
ImGui::BeginDisabled(this->m_matcherTask.isRunning());
{
if (ImGui::BeginCombo("hex.builtin.view.yara.header.rules"_lang, this->m_rules[this->m_selectedRule].first.string().c_str())) {
for (u32 i = 0; i < this->m_rules.size(); i++) {
@@ -63,7 +63,7 @@ namespace hex::plugin::builtin {
}
ImGui::EndDisabled();
if (this->m_matching) {
if (this->m_matcherTask.isRunning()) {
ImGui::SameLine();
ImGui::TextSpinner("hex.builtin.view.yara.matching"_lang);
}
@@ -86,7 +86,7 @@ namespace hex::plugin::builtin {
ImGui::TableHeadersRow();
if (!this->m_matching) {
if (!this->m_matcherTask.isRunning()) {
ImGuiListClipper clipper;
clipper.Begin(this->m_matches.size());
@@ -173,19 +173,13 @@ namespace hex::plugin::builtin {
void ViewYara::applyRules() {
this->clearResult();
this->m_matching = true;
std::thread([this] {
this->m_matcherTask = TaskManager::createTask("hex.builtin.view.yara.matching", 0, [this](auto &task) {
if (!ImHexApi::Provider::isValid()) return;
auto provider = ImHexApi::Provider::get();
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.yara.matching", provider->getActualSize());
YR_COMPILER *compiler = nullptr;
yr_compiler_create(&compiler);
ON_SCOPE_EXIT {
yr_compiler_destroy(compiler);
this->m_matching = false;
};
yr_compiler_set_include_callback(
@@ -209,8 +203,8 @@ namespace hex::plugin::builtin {
delete[] ptr;
},
fs::toShortPath(this->m_rules[this->m_selectedRule].second).string().data());
fs::toShortPath(this->m_rules[this->m_selectedRule].second).string().data()
);
fs::File file(this->m_rules[this->m_selectedRule].second, fs::File::Mode::Read);
if (!file.isValid()) return;
@@ -220,7 +214,7 @@ namespace hex::plugin::builtin {
yr_compiler_get_error_message(compiler, errorMessage.data(), errorMessage.size());
hex::trim(errorMessage);
ImHexApi::Tasks::doLater([this, errorMessage] {
TaskManager::doLater([this, errorMessage] {
this->clearResult();
this->m_consoleMessages.push_back("Error: " + errorMessage);
@@ -246,15 +240,14 @@ namespace hex::plugin::builtin {
context.currBlock.base = 0;
context.currBlock.fetch_data = [](auto *block) -> const u8 * {
auto &context = *static_cast<ScanContext *>(block->context);
auto provider = ImHexApi::Provider::get();
context.buffer.resize(context.currBlock.size);
if (context.buffer.empty()) return nullptr;
if (context.buffer.empty())
return nullptr;
block->size = context.currBlock.size;
provider->read(context.currBlock.base + provider->getBaseAddress(), context.buffer.data(), context.buffer.size());
return context.buffer.data();
@@ -301,11 +294,11 @@ namespace hex::plugin::builtin {
ResultContext resultContext;
yr_rules_scan_mem_blocks(
rules, &iterator, 0, [](YR_SCAN_CONTEXT *context, int message, void *data, void *userData) -> int {
auto &results = *static_cast<ResultContext *>(userData);
rules, &iterator, 0, [](YR_SCAN_CONTEXT *context, int message, void *data, void *userData) -> int {
auto &results = *static_cast<ResultContext *>(userData);
switch (message) {
case CALLBACK_MSG_RULE_MATCHING:
switch (message) {
case CALLBACK_MSG_RULE_MATCHING:
{
auto rule = static_cast<YR_RULE *>(data);
@@ -315,30 +308,30 @@ namespace hex::plugin::builtin {
if (rule->strings != nullptr) {
yr_rule_strings_foreach(rule, string) {
yr_string_matches_foreach(context, string, match) {
results.newMatches.push_back({ rule->identifier, string->identifier, u64(match->offset), size_t(match->match_length), false, 0, 0 });
}
results.newMatches.push_back({ rule->identifier, string->identifier, u64(match->offset), size_t(match->match_length), false, 0, 0 });
}
}
} else {
results.newMatches.push_back({ rule->identifier, "", 0, 0, true, 0, 0 });
}
}
break;
case CALLBACK_MSG_CONSOLE_LOG:
break;
case CALLBACK_MSG_CONSOLE_LOG:
{
results.consoleMessages.emplace_back(static_cast<const char *>(data));
}
break;
default:
break;
}
break;
default:
break;
}
return CALLBACK_CONTINUE;
},
&resultContext,
0);
return CALLBACK_CONTINUE;
},
&resultContext,
0);
ImHexApi::Tasks::doLater([this, resultContext] {
TaskManager::doLater([this, resultContext] {
this->m_matches = resultContext.newMatches;
this->m_consoleMessages = resultContext.consoleMessages;
@@ -348,7 +341,7 @@ namespace hex::plugin::builtin {
match.tooltipId = ImHexApi::HexEditor::addTooltip({ match. address, match.size }, hex::format("{0} [{1}]", match.identifier, match.variable), YaraColor);
}
});
}).detach();
});
}
}