From 7a845519ce53c4efd5c5db9eb8fc815fdd69fe2f Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Tue, 18 Jun 2019 22:47:08 +0200 Subject: [PATCH] Fix a possible deadlock in CEF. --- nageru/cef_capture.cpp | 13 +++++++++++-- nageru/cef_capture.h | 2 +- nageru/mixer.cpp | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/nageru/cef_capture.cpp b/nageru/cef_capture.cpp index 09c451f..9524861 100644 --- a/nageru/cef_capture.cpp +++ b/nageru/cef_capture.cpp @@ -97,8 +97,17 @@ void CEFCapture::resize(unsigned width, unsigned height) this->height = height; } -void CEFCapture::request_new_frame() +void CEFCapture::request_new_frame(bool ignore_if_locked) { + unique_lock outer_lock(browser_mutex, defer_lock); + if (ignore_if_locked && !outer_lock.try_lock()) { + // If the caller is holding card_mutex, we need to abort here + // if we can't get browser_mutex, since otherwise, the UI thread + // might hold browser_mutex (blocking post_to_cef_ui_thread()) + // and be waiting for card_mutex. + return; + } + // By adding a delay, we make sure we don't get a new frame // delivered immediately (we probably already are on the UI thread), // where we couldn't really deal with it. @@ -129,7 +138,7 @@ void CEFCapture::OnPaint(const void *buffer, int width, int height) // (CEF only sends OnPaint when there are actual changes, // so we need to do this explicitly, or we could be stuck on an // old frame forever if the image doesn't change.) - request_new_frame(); + request_new_frame(/*ignore_if_locked=*/false); ++timecode; } else { assert(video_frame.size >= unsigned(width * height * 4)); diff --git a/nageru/cef_capture.h b/nageru/cef_capture.h index 2b4d1cb..cc3c67c 100644 --- a/nageru/cef_capture.h +++ b/nageru/cef_capture.h @@ -85,7 +85,7 @@ public: void set_max_fps(int max_fps); void execute_javascript_async(const std::string &js); void resize(unsigned width, unsigned height); - void request_new_frame(); + void request_new_frame(bool ignore_if_locked); // Callbacks from NageruCEFClient. void OnPaint(const void *buffer, int width, int height); diff --git a/nageru/mixer.cpp b/nageru/mixer.cpp index 91c82d4..c9f7ed7 100644 --- a/nageru/mixer.cpp +++ b/nageru/mixer.cpp @@ -1270,7 +1270,7 @@ start: // we dropped. (may_have_dropped_last_frame is set whenever we // trim the queue completely away, and cleared when we actually // get a new frame.) - ((CEFCapture *)card->capture.get())->request_new_frame(); + ((CEFCapture *)card->capture.get())->request_new_frame(/*ignore_if_locked=*/true); } #endif } else { -- 2.39.2