From 06ea7bf1d9e0470d49285b42c1e8feb7c558bcea Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 7 Aug 2021 09:55:56 +0200 Subject: [PATCH] Fix crash when deleting macro with wait action Note that this might still not be completely race free but should improve the situation a lot. --- src/advanced-scene-switcher.cpp | 3 ++- src/headers/switcher-data-structs.hpp | 3 ++- src/macro-action-edit.cpp | 2 ++ src/macro-action-wait.cpp | 8 +++++--- src/macro-tab.cpp | 2 ++ src/macro.cpp | 2 +- 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index 7986f2cd..f2acd7db 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -424,8 +424,9 @@ void SwitcherData::Stop() { if (th && th->isRunning()) { stop = true; - transitionCv.notify_one(); cv.notify_one(); + abortMacroWait = true; + macroWaitCv.notify_one(); th->wait(); delete th; th = nullptr; diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index d757fe63..791b94c5 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -67,7 +67,6 @@ struct SwitcherData { std::mutex m; bool transitionActive = false; bool waitForTransition = false; - std::condition_variable transitionCv; bool stop = false; bool verbose = false; bool disableHints = false; @@ -92,6 +91,8 @@ struct SwitcherData { std::chrono::high_resolution_clock::time_point lastMatchTime; std::deque macros; + std::condition_variable macroWaitCv; + std::atomic_bool abortMacroWait = {false}; bool macroSceneSwitched = false; bool replayBufferSaved = false; diff --git a/src/macro-action-edit.cpp b/src/macro-action-edit.cpp index 07b5c829..5a935a99 100644 --- a/src/macro-action-edit.cpp +++ b/src/macro-action-edit.cpp @@ -174,6 +174,8 @@ void AdvSceneSwitcher::RemoveMacroAction(int idx) std::lock_guard lock(switcher->m); macro->Actions().erase(macro->Actions().begin() + idx); + switcher->abortMacroWait = true; + switcher->macroWaitCv.notify_one(); macro->UpdateActionIndices(); // All entry pointers in existing edit widgets after the new entry will diff --git a/src/macro-action-wait.cpp b/src/macro-action-wait.cpp index 8ce168f4..44e6ad22 100644 --- a/src/macro-action-wait.cpp +++ b/src/macro-action-wait.cpp @@ -38,10 +38,12 @@ bool MacroActionWait::PerformAction() sleep_duration); std::unique_lock lock(switcher->m); - auto r = switcher->cv.wait_for( + switcher->abortMacroWait = false; + switcher->macroWaitCv.wait_for( lock, - std::chrono::milliseconds((long long)(sleep_duration * 1000))); - return r == std::cv_status::timeout; + std::chrono::milliseconds((long long)(sleep_duration * 1000)), + [] { return switcher->abortMacroWait.load(); }); + return !switcher->abortMacroWait; } bool MacroActionWait::Save(obs_data_t *obj) diff --git a/src/macro-tab.cpp b/src/macro-tab.cpp index e3d363aa..860cd1f7 100644 --- a/src/macro-tab.cpp +++ b/src/macro-tab.cpp @@ -80,6 +80,8 @@ void AdvSceneSwitcher::on_macroRemove_clicked() QString name; { std::lock_guard lock(switcher->m); + switcher->abortMacroWait = true; + switcher->macroWaitCv.notify_one(); int idx = ui->macros->currentRow(); QString::fromStdString(switcher->macros[idx].Name()); switcher->macros.erase(switcher->macros.begin() + idx); diff --git a/src/macro.cpp b/src/macro.cpp index b2b6a758..b024fd6d 100644 --- a/src/macro.cpp +++ b/src/macro.cpp @@ -107,8 +107,8 @@ bool Macro::PerformAction() { bool ret = true; for (auto &a : _actions) { - ret = ret && a->PerformAction(); a->LogAction(); + ret = ret && a->PerformAction(); if (!ret) { return false; }