From 3c94aabdf49f6e7d0c4b013a25a7cfcafb3d2eb2 Mon Sep 17 00:00:00 2001 From: Richard Osborne Date: Wed, 24 Sep 2025 11:53:36 -0500 Subject: [PATCH 1/2] update mac-obs-browser to not block main thread (CefRunMessageLoop) * call CefDoMessageLoopWork instead of CefRunMessageLoop which is a blocking call * QoL change for dev: update ExecuteTask/ExecuteSyncTask to check if invoked on main thread. When debugging slobs, we're on main thread. But when this code is invoked from SLD, we're running from an async thread. so this code enables the task to be executed with no thought or care where its been run from. --- browser-mac.h | 2 ++ browser-mac.mm | 36 ++++++++++++++++++++++++++++++++---- obs-browser-plugin.cpp | 26 ++++++++++++++++---------- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/browser-mac.h b/browser-mac.h index cb07721ee..514b9c02c 100644 --- a/browser-mac.h +++ b/browser-mac.h @@ -44,6 +44,8 @@ bool ExecuteNextBrowserTask(); void ExecuteTask(MessageTask task); void ExecuteSyncTask(MessageTask task); void DoCefMessageLoop(int ms); +void DoCefMessageLoopTimer(float ms); +void StopCefMessageLoopTimer(); void Process(); #if 0 // REMOVE_DUPLICATE void QueueBrowserTask(CefRefPtr browser, BrowserFunc func); diff --git a/browser-mac.mm b/browser-mac.mm index 0606801ab..bf94dd125 100644 --- a/browser-mac.mm +++ b/browser-mac.mm @@ -45,16 +45,26 @@ bool ExecuteNextBrowserTask() void ExecuteTask(MessageTask task) { - dispatch_async(dispatch_get_main_queue(), ^{ + // Protect against exception if already on main thread + if ([NSThread isMainThread]) { task(); - }); + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + task(); + }); + } } void ExecuteSyncTask(MessageTask task) { - dispatch_sync(dispatch_get_main_queue(), ^{ + // Protect against exception if already on main thread + if ([NSThread isMainThread]) { task(); - }); + } else { + dispatch_sync(dispatch_get_main_queue(), ^{ + task(); + }); + } } void DoCefMessageLoop(int) @@ -64,6 +74,24 @@ void DoCefMessageLoop(int) }); } +static NSTimer *cefTimer = nil; + +void DoCefMessageLoopTimer(float ms) +{ + cefTimer = [NSTimer + scheduledTimerWithTimeInterval:ms + repeats:YES + block:^(NSTimer *) { + CefDoMessageLoopWork(); + }]; +} + +void StopCefMessageLoopTimer() +{ + [cefTimer invalidate]; + cefTimer = nil; +} + void Process() { dispatch_async(dispatch_get_main_queue(), ^{ diff --git a/obs-browser-plugin.cpp b/obs-browser-plugin.cpp index 2db193608..fb6211ff2 100644 --- a/obs-browser-plugin.cpp +++ b/obs-browser-plugin.cpp @@ -333,7 +333,8 @@ static obs_data_array_t *browser_source_get_messages(void *data) messages = obs_data_array_create(); for (const auto &message : bs->messagesToApp) { obs_data_t *msg_data = obs_data_create(); - obs_data_set_string(msg_data, "message", message.c_str()); + obs_data_set_string(msg_data, "message", + message.c_str()); obs_data_array_push_back(messages, msg_data); obs_data_release(msg_data); } @@ -529,15 +530,9 @@ static void BrowserShutdown(void) #ifndef ENABLE_BROWSER_QT_LOOP static void BrowserManagerThread(obs_data_t *settings) { -#ifdef __APPLE__ - ExecuteSyncTask([&settings]() { -#endif - BrowserInit(settings); - CefRunMessageLoop(); - BrowserShutdown(); -#ifdef __APPLE__ - }); -#endif + BrowserInit(settings); + CefRunMessageLoop(); + BrowserShutdown(); } #endif @@ -546,6 +541,12 @@ extern "C" EXPORT void obs_browser_initialize(obs_data_t *settings) if (!os_atomic_set_bool(&manager_initialized, true)) { #ifdef ENABLE_BROWSER_QT_LOOP BrowserInit(settings); +#elif __APPLE__ + + ExecuteTask([&settings]() { + BrowserInit(settings); + DoCefMessageLoopTimer(0.01f); // Do not block the main queue so we avoid calling CefRunMessageLoop() + }); #else auto binded_fn = bind(BrowserManagerThread, settings); manager_thread = thread(binded_fn); @@ -956,6 +957,11 @@ void obs_module_unload(void) { #ifdef USE_UI_LOOP BrowserShutdown(); +#elif __APPLE__ + ExecuteSyncTask([]() { + StopCefMessageLoopTimer(); + BrowserShutdown(); + }); #else if (manager_thread.joinable()) { while (!QueueCEFTask([]() { CefQuitMessageLoop(); })) From aea2b28f09a659f3956a68697d455297f862c2b4 Mon Sep 17 00:00:00 2001 From: Richard Osborne Date: Wed, 24 Sep 2025 12:03:50 -0500 Subject: [PATCH 2/2] declare cefTimer a top of file --- browser-mac.mm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/browser-mac.mm b/browser-mac.mm index bf94dd125..52ef1ca23 100644 --- a/browser-mac.mm +++ b/browser-mac.mm @@ -26,6 +26,7 @@ std::mutex browserTaskMutex; std::deque browserTasks; +static NSTimer *cefTimer = nil; bool ExecuteNextBrowserTask() { @@ -74,8 +75,6 @@ void DoCefMessageLoop(int) }); } -static NSTimer *cefTimer = nil; - void DoCefMessageLoopTimer(float ms) { cefTimer = [NSTimer