From 1c4a6ca6c67d723d6729c357f59e5b2db768096f Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 26 Feb 2019 06:37:01 -0800 Subject: [PATCH] UI: Make workaround for Logitech plugin hard lock In commit d17ee20863, we attempted to fix a race condition crash in the Logitech plugin by deferring the "stream/recording/replay buffer active" calls to the UI thread. However, the Logitech plugin loop_function funciton can call obs_frontend_streaming_active/etc functions while the UI thread waits for the loop_function thread for many OBS events, causing a hard lock in the Logitech plugin. This fixes that by making the obs_frontend_streaming_active/etc functions completely atomic instead. It's a bit of a hack but it's better than accessing objects. --- UI/api-interface.cpp | 25 +++++++------------------ UI/window-basic-main-outputs.cpp | 10 ++++++++++ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/UI/api-interface.cpp b/UI/api-interface.cpp index 4327a00c2..705caaa4b 100644 --- a/UI/api-interface.cpp +++ b/UI/api-interface.cpp @@ -20,6 +20,10 @@ static T GetOBSRef(QListWidgetItem *item) void EnumProfiles(function &&cb); void EnumSceneCollections(function &&cb); +extern volatile bool streaming_active; +extern volatile bool recording_active; +extern volatile bool replaybuf_active; + /* ------------------------------------------------------------------------- */ template struct OBSStudioCallback { @@ -232,12 +236,7 @@ struct OBSStudioAPI : obs_frontend_callbacks { bool obs_frontend_streaming_active(void) override { - bool active; - QMetaObject::invokeMethod(main, - "StreamingActive", - WaitConnection(), - Q_RETURN_ARG(bool, active)); - return active; + return os_atomic_load_bool(&streaming_active); } void obs_frontend_recording_start(void) override @@ -252,12 +251,7 @@ struct OBSStudioAPI : obs_frontend_callbacks { bool obs_frontend_recording_active(void) override { - bool active; - QMetaObject::invokeMethod(main, - "RecordingActive", - WaitConnection(), - Q_RETURN_ARG(bool, active)); - return active; + return os_atomic_load_bool(&recording_active); } void obs_frontend_replay_buffer_start(void) override @@ -277,12 +271,7 @@ struct OBSStudioAPI : obs_frontend_callbacks { bool obs_frontend_replay_buffer_active(void) override { - bool active; - QMetaObject::invokeMethod(main, - "ReplayBufferActive", - WaitConnection(), - Q_RETURN_ARG(bool, active)); - return active; + return os_atomic_load_bool(&replaybuf_active); } void *obs_frontend_add_tools_menu_qaction(const char *name) override diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp index a6bc98c37..05cb30876 100644 --- a/UI/window-basic-main-outputs.cpp +++ b/UI/window-basic-main-outputs.cpp @@ -10,6 +10,10 @@ using namespace std; extern bool EncoderAvailable(const char *encoder); +volatile bool streaming_active = false; +volatile bool recording_active = false; +volatile bool replaybuf_active = false; + static void OBSStreamStarting(void *data, calldata_t *params) { BasicOutputHandler *output = static_cast(data); @@ -41,6 +45,7 @@ static void OBSStartStreaming(void *data, calldata_t *params) { BasicOutputHandler *output = static_cast(data); output->streamingActive = true; + os_atomic_set_bool(&streaming_active, true); QMetaObject::invokeMethod(output->main, "StreamingStart"); UNUSED_PARAMETER(params); @@ -56,6 +61,7 @@ static void OBSStopStreaming(void *data, calldata_t *params) output->streamingActive = false; output->delayActive = false; + os_atomic_set_bool(&streaming_active, false); QMetaObject::invokeMethod(output->main, "StreamingStop", Q_ARG(int, code), Q_ARG(QString, arg_last_error)); } @@ -65,6 +71,7 @@ static void OBSStartRecording(void *data, calldata_t *params) BasicOutputHandler *output = static_cast(data); output->recordingActive = true; + os_atomic_set_bool(&recording_active, true); QMetaObject::invokeMethod(output->main, "RecordingStart"); UNUSED_PARAMETER(params); @@ -76,6 +83,7 @@ static void OBSStopRecording(void *data, calldata_t *params) int code = (int)calldata_int(params, "code"); output->recordingActive = false; + os_atomic_set_bool(&recording_active, false); QMetaObject::invokeMethod(output->main, "RecordingStop", Q_ARG(int, code)); @@ -95,6 +103,7 @@ static void OBSStartReplayBuffer(void *data, calldata_t *params) BasicOutputHandler *output = static_cast(data); output->replayBufferActive = true; + os_atomic_set_bool(&replaybuf_active, true); QMetaObject::invokeMethod(output->main, "ReplayBufferStart"); UNUSED_PARAMETER(params); @@ -106,6 +115,7 @@ static void OBSStopReplayBuffer(void *data, calldata_t *params) int code = (int)calldata_int(params, "code"); output->replayBufferActive = false; + os_atomic_set_bool(&replaybuf_active, false); QMetaObject::invokeMethod(output->main, "ReplayBufferStop", Q_ARG(int, code));