From 49501be2a3d037db3cea216539b8dfdb397aae91 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Mon, 6 Jul 2015 09:02:13 -0700 Subject: [PATCH] UI: Fix potential deadlocks when saving SaveProject calls obs functions that locks certain mutexes, and because I made it so that SaveProject was being called inside of certain signal handlers (which could already be locked in other mutexes), it could cause a mutual deadlock with other threads. This fix puts the main project saving code in to SaveProjectDeferred, then pushes it on to the Qt message queue to safely save outside of those locks. It's a function that's perfectly safe to put on the message queue because it will automatically be disabled in certain circumstances where it would be unsafe to call, such as on shutdown. This code will also make it so that the project will not needlessly be saved more than once if the SaveProjectDeferred call was pushed multiple times on to the queue. --- obs/window-basic-main.cpp | 15 +++++++++++++++ obs/window-basic-main.hpp | 2 ++ 2 files changed, 17 insertions(+) diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp index 601b0d5ec..235bd6ed7 100644 --- a/obs/window-basic-main.cpp +++ b/obs/window-basic-main.cpp @@ -1103,6 +1103,21 @@ void OBSBasic::SaveProject() if (disableSaving) return; + projectChanged = true; + QMetaObject::invokeMethod(this, "SaveProjectDeferred", + Qt::QueuedConnection); +} + +void OBSBasic::SaveProjectDeferred() +{ + if (disableSaving) + return; + + if (!projectChanged) + return; + + projectChanged = false; + const char *sceneCollection = config_get_string(App()->GlobalConfig(), "Basic", "SceneCollectionFile"); char savePath[512]; diff --git a/obs/window-basic-main.hpp b/obs/window-basic-main.hpp index bd475f569..e81f3d5e6 100644 --- a/obs/window-basic-main.hpp +++ b/obs/window-basic-main.hpp @@ -75,6 +75,7 @@ private: bool loaded = false; long disableSaving = 1; + bool projectChanged = false; QPointer updateCheckThread; QPointer logUploadThread; @@ -197,6 +198,7 @@ public slots: void RecordingStart(); void RecordingStop(int code); + void SaveProjectDeferred(); void SaveProject(); private slots: