Skip to content

fix: dangling raw_ptr regression in DesktopCapturer#51158

Merged
ckerr merged 1 commit into
mainfrom
fix/dangling-raw-ptr-in-new-DesktopCapturer-code
Apr 20, 2026
Merged

fix: dangling raw_ptr regression in DesktopCapturer#51158
ckerr merged 1 commit into
mainfrom
fix/dangling-raw-ptr-in-new-DesktopCapturer-code

Conversation

@ckerr

@ckerr ckerr commented Apr 19, 2026

Copy link
Copy Markdown
Member

Description of Change

Fix a main-only bug introduced last week by #50960.

This change fixes a dangling raw_ptr in DesktopCapturer that was caused by freeing window_observer_ and screen_observer_ before destroying window_capturer_ and screen_capturer_. Since DesktopMediaListBase keeps a raw_ptr to the observer, the order of freeing those needs to be reversed.

Fixes this error:

[DanglingPtr](1/3) A raw_ptr/raw_ref is dangling.

[DanglingPtr](2/3) First, the memory was freed at:

Stack trace:
#0 0x59a886410092 base::debug::CollectStackTrace() [../../base/debug/stack_trace_posix.cc:1050:7]
#1 0x59a8863f7531 base::debug::StackTrace::StackTrace() [../../base/debug/stack_trace.cc:280:20]
#2 0x59a886417d46 base::allocator::(anonymous namespace)::DanglingRawPtrDetected() [../../base/allocator/partition_alloc_support.cc:438:11]
#3 0x59a8864d68ab allocator_shim::internal::PartitionAllocFunctionsInternal<>::FreeWithSize() [../../base/allocator/partition_allocator/src/partition_alloc/in_slot_metadata.h:389:5]
#4 0x59a87f0d9cd2 electron::api::DesktopCapturer::HandleFailure() [../../third_party/libc++/src/include/__memory/unique_ptr.h:74:5]
#5 0x59a87f08f5c1 base::OnceCallback<>::Run() [../../base/functional/callback.h:155:12]
#6 0x59a88635bc11 base::TaskAnnotator::RunTaskImpl() [../../base/task/common/task_annotator.cc:229:34]
#7 0x59a886392f73 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl() [../../base/task/common/task_annotator.h:112:5]
#8 0x59a88639239b base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() [../../base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:340:40]
#9 0x59a886432b65 base::MessagePumpGlib::Run() [../../base/message_loop/message_pump_glib.cc:782:48]
#10 0x59a8863940ca base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run() [../../base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:651:12]
#11 0x59a886338e12 base::RunLoop::Run() [../../base/run_loop.cc:135:14]
#12 0x59a884170531 content::BrowserMainLoop::RunMainMessageLoop() [../../content/browser/browser_main_loop.cc:1105:18]
#13 0x59a884172a61 content::BrowserMainRunnerImpl::Run() [../../content/browser/browser_main_runner_impl.cc:151:15]
#14 0x59a88416c352 content::BrowserMain() [../../content/browser/browser_main.cc:32:28]
#15 0x59a87f8b66c7 content::RunBrowserProcessMain() [../../content/app/content_main_runner_impl.cc:701:10]
#16 0x59a87f8b9bc7 content::ContentMainRunnerImpl::RunBrowser() [../../content/app/content_main_runner_impl.cc:1325:10]
#17 0x59a87f8b8ec6 content::ContentMainRunnerImpl::Run() [../../content/app/content_main_runner_impl.cc:1155:12]
#18 0x59a87f8b4d52 content::RunContentProcess() [../../content/app/content_main.cc:356:36]
#19 0x59a87f8b4f40 content::ContentMain() [../../content/app/content_main.cc:369:10]
#20 0x59a87f083591 main [../../electron/shell/app/electron_main_linux.cc:50:10]
#21 0x7df21a82a575 (/usr/lib/x86_64-linux-gnu/libc.so.6+0x2a574)
#22 0x7df21a82a628 __libc_start_main
#23 0x59a87f06702a _start

Task trace:
#0 0x59a87f0da22e electron::api::DesktopCapturer::ListObserver::OnDelegatedSourceListDismissed() [../../electron/shell/browser/api/electron_api_desktop_capturer.cc:291:9]
#1 0x59a88db2ca5c NativeDesktopMediaList::Worker::OnError() [../../chrome/browser/media/webrtc/native_desktop_media_list.cc:754:7]

[DanglingPtr](3/3) Later, the dangling raw_ptr was released at:

Stack trace:
#0 0x59a886410092 base::debug::CollectStackTrace() [../../base/debug/stack_trace_posix.cc:1050:7]
#1 0x59a8863f7531 base::debug::StackTrace::StackTrace() [../../base/debug/stack_trace.cc:280:20]
#2 0x59a886417e2d base::allocator::(anonymous namespace)::DanglingRawPtrReleased<>() [../../base/allocator/partition_alloc_support.cc:600:21]
#3 0x59a886457169 base::internal::RawPtrBackupRefImpl<>::ReleaseInternal() [../../base/allocator/partition_allocator/src/partition_alloc/in_slot_metadata.h:211:7]
#4 0x59a88db2fb44 DesktopMediaListBase::~DesktopMediaListBase() [../../base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.h:194:7]
#5 0x59a88db2d2c6 NativeDesktopMediaList::~NativeDesktopMediaList() [../../chrome/browser/media/webrtc/native_desktop_media_list.cc:820:1]
#6 0x59a88db2d2fe NativeDesktopMediaList::~NativeDesktopMediaList() [../../chrome/browser/media/webrtc/native_desktop_media_list.cc:808:51]
#7 0x59a87f0d9ce9 electron::api::DesktopCapturer::HandleFailure() [../../third_party/libc++/src/include/__memory/unique_ptr.h:74:5]
#8 0x59a87f08f5c1 base::OnceCallback<>::Run() [../../base/functional/callback.h:155:12]
#9 0x59a88635bc11 base::TaskAnnotator::RunTaskImpl() [../../base/task/common/task_annotator.cc:229:34]
#10 0x59a886392f73 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl() [../../base/task/common/task_annotator.h:112:5]
#11 0x59a88639239b base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() [../../base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:340:40]
#12 0x59a886432b65 base::MessagePumpGlib::Run() [../../base/message_loop/message_pump_glib.cc:782:48]
#13 0x59a8863940ca base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run() [../../base/task/sequence_manager/thread_controller_with_message_pump_impl.cc:651:12]
#14 0x59a886338e12 base::RunLoop::Run() [../../base/run_loop.cc:135:14]
#15 0x59a884170531 content::BrowserMainLoop::RunMainMessageLoop() [../../content/browser/browser_main_loop.cc:1105:18]
#16 0x59a884172a61 content::BrowserMainRunnerImpl::Run() [../../content/browser/browser_main_runner_impl.cc:151:15]
#17 0x59a88416c352 content::BrowserMain() [../../content/browser/browser_main.cc:32:28]
#18 0x59a87f8b66c7 content::RunBrowserProcessMain() [../../content/app/content_main_runner_impl.cc:701:10]
#19 0x59a87f8b9bc7 content::ContentMainRunnerImpl::RunBrowser() [../../content/app/content_main_runner_impl.cc:1325:10]
#20 0x59a87f8b8ec6 content::ContentMainRunnerImpl::Run() [../../content/app/content_main_runner_impl.cc:1155:12]
#21 0x59a87f8b4d52 content::RunContentProcess() [../../content/app/content_main.cc:356:36]
#22 0x59a87f8b4f40 content::ContentMain() [../../content/app/content_main.cc:369:10]
#23 0x59a87f083591 main [../../electron/shell/app/electron_main_linux.cc:50:10]
#24 0x7df21a82a575 (/usr/lib/x86_64-linux-gnu/libc.so.6+0x2a574)
#25 0x7df21a82a628 __libc_start_main
#26 0x59a87f06702a _start

Task trace:
#0 0x59a87f0da22e electron::api::DesktopCapturer::ListObserver::OnDelegatedSourceListDismissed() [../../electron/shell/browser/api/electron_api_desktop_capturer.cc:291:9]
#1 0x59a88db2ca5c NativeDesktopMediaList::Worker::OnError() [../../chrome/browser/media/webrtc/native_desktop_media_list.cc:754:7]

Tested by making this change locally:

diff --git a/build/args/all.gn b/build/args/all.gn
index 45939f456f..7624114b5f 100644
--- a/build/args/all.gn
+++ b/build/args/all.gn
@@ -53,8 +53,12 @@ use_qt6 = false
 
 # https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md
 # TODO(vertedinde): hunt down dangling pointers on Linux
-enable_dangling_raw_ptr_checks = false
-enable_dangling_raw_ptr_feature_flag = false
+is_debug = true
+enable_dangling_raw_ptr_checks = true
+enable_dangling_raw_ptr_feature_flag = true
+enable_backup_ref_ptr_support = true
+enable_backup_ref_ptr_feature_flag = true
+enable_backup_ref_ptr_instance_tracer = true
 
 # This flag speeds up the performance of fork/execve on linux systems.
 # Ref: https://chromium-review.googlesource.com/c/v8/v8/+/4602858

Checklist

Release Notes

Notes: none.

@ckerr ckerr added semver/patch backwards-compatible bug fixes no-backport labels Apr 19, 2026
@electron-cation electron-cation Bot added the new-pr 🌱 PR opened recently label Apr 19, 2026
@ckerr ckerr merged commit bef68b6 into main Apr 20, 2026
129 of 131 checks passed
@ckerr ckerr deleted the fix/dangling-raw-ptr-in-new-DesktopCapturer-code branch April 20, 2026 15:26
@release-clerk

release-clerk Bot commented Apr 20, 2026

Copy link
Copy Markdown

No Release Notes

ckerr added a commit that referenced this pull request May 6, 2026
* fix: timing issue DCHECK crash in DesktopCapturer on macOS (#50960)

refactor: use StartUpdating in desktopCapturer

Replace the one-shot Update() callback model with the continuous
StartUpdating() observer model for NativeDesktopMediaList.

Fixes a macOS DCHECK(can_refresh()) crash in UpdateSourceThumbnail(),
where ScreenCaptureKit's recurrent thumbnail capturer would post
UpdateSourceThumbnail callbacks after the one-shot refresh_callback_
had been consumed. Now, can_refresh() is always true because
refresh_callback_ is repopulated via ScheduleNextRefresh().

Each capturer (window, screen) gets its own ListObserver that tracks
readiness via OnSourceAdded and OnSourceThumbnailChanged events.
Once a list has both sources and thumbnails (or thumbnails aren't
requested), its data is snapshotted and the capturer checks if all
requested types are ready before resolving to JS.

Also remove the "skip_next_refresh_" Chromium patch, which was a
workaround for the timing mismatch between the one-shot Update()
model and ScreenCaptureKit's asynchronous thumbnail delivery.

refactor: simplify state logic in DesktopCapturer
(cherry picked from commit dad4ab6)

* fix: do not block indefinitely on thumbnails in desktopCapturer (#51128)

* fix: do not block indefinitely on thumbnails in desktopCapturer

fixes dad4ab6 regression

* fix: build error

* fixup! fix: do not block indefinitely on thumbnails in desktopCapturer

chore: remove unnecessary code

* Update shell/browser/api/electron_api_desktop_capturer.cc

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

---------

Co-authored-by: Niklas Wenzel <dev@nikwen.de>
(cherry picked from commit a1d28e6)

* fix: dangling `raw_ptr` regression in `DesktopCapturer` (#51158)

fix: dangling raw_ptr in desktopCapturer
(cherry picked from commit bef68b6)

* fix: do not pass a `DesktopMediaList* to DesktopCapturer::OnListReady()` (#51399)

refactor: do not pass a DesktopMediaList* to DesktopCapturer::OnListReady()

The list pointer was being used as a proxy for its type, so just pass
the type instead. This solves a lifecycle issue occurring in CI where
the callack can outlive the DesktopMediaList.

Sample error log:

[48471:0428/193441.269750:FATAL:base/allocator/partition_alloc_support.cc:798] Detected dangling raw_ptr in unretained with id=0x0000013c02e14378:
 Task trace:
 0   Electron Framework  0x000000012283a0ba electron::api::DesktopCapturer::ListObserver::MaybeNotifyReady() + 170
 1   Electron Framework  0x0000000133246dc5 NativeDesktopMediaList::Worker::OnRecurrentCaptureResult(webrtc::DesktopCapturer::Result, std::__Cr::unique_ptr<webrtc::DesktopFrame, std::__Cr::default_delete<webrtc::DesktopFrame>>, long) + 357
 2   Electron Framework  0x000000013328dbcf (anonymous namespace)::ScreenshotManagerCapturer::OnRecurrentCaptureTimer() + 1343
 Stack trace:
 0   Electron Framework  0x000000012ade42f2 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 18
 1   Electron Framework  0x000000012add00e1 base::debug::StackTrace::StackTrace(unsigned long) + 225
 2   Electron Framework  0x000000012ade978a base::allocator::UnretainedDanglingRawPtrDetectedCrash(unsigned long) + 90
 3   Electron Framework  0x000000012ae437f7 base::internal::RawPtrBackupRefImpl<true>::ReportIfDanglingInternal(unsigned long) + 391

(cherry picked from commit f8d0412)

---------

Co-authored-by: Charles Kerr <charles@charleskerr.com>
Co-authored-by: Niklas Wenzel <dev@nikwen.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new-pr 🌱 PR opened recently no-backport semver/patch backwards-compatible bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants