Browse Source

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.
jp9000 6 years ago
parent
commit
1c4a6ca6c6
2 changed files with 17 additions and 18 deletions
  1. 7 18
      UI/api-interface.cpp
  2. 10 0
      UI/window-basic-main-outputs.cpp

+ 7 - 18
UI/api-interface.cpp

@@ -20,6 +20,10 @@ static T GetOBSRef(QListWidgetItem *item)
 void EnumProfiles(function<bool (const char *, const char *)> &&cb);
 void EnumSceneCollections(function<bool (const char *, const char *)> &&cb);
 
+extern volatile bool streaming_active;
+extern volatile bool recording_active;
+extern volatile bool replaybuf_active;
+
 /* ------------------------------------------------------------------------- */
 
 template<typename T> 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

+ 10 - 0
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<BasicOutputHandler*>(data);
@@ -41,6 +45,7 @@ static void OBSStartStreaming(void *data, calldata_t *params)
 {
 	BasicOutputHandler *output = static_cast<BasicOutputHandler*>(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<BasicOutputHandler*>(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<BasicOutputHandler*>(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));