panel: Update browser shutdown code to ensure proper sequence of events #506
No reviewers
Labels
No labels
area/accessibility
area/dependency
Confirmed
Crash Report
Delayed
Design Issue
Duplicate
Feedback required
Good first issue
kind/bug
kind/cleanup
kind/enhancement
platform/linux
platform/macos
platform/windows
priority/high
Question
Request for Comments
Seeking Other Contributors
Seeking Testers
Won't Fix / By Design
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-obsproject/obs-browser!506
Loading…
Reference in a new issue
No description provided.
Delete branch "browser-close-fix"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description
Rewrites the browser shutdown code to be more explicit about its functionality and the sequence of events that should take place in a serial order to ensure that the browser process is properly shut down before the associated Qt widgetry is destroyed.
Motivation and Context
When the underlying CEF browser instance is required to close (either because the widget itself is being destroyed or because the associated function was called explicitly) a specific sequence of events needs to be ensured and also needs to block the thread it was called on.
This is necessary to ensure that CEF's own shutdown code can run to completion before Qt continues with its own widget destruction and cleanup code.
This change splits the procedure into 3 separate steps, each scheduled to run in-order on the local event loop to simulate a "serial dispatch queue":
Step 3 is either executed after the "OnBeforeClose" lifetime event is signaled by CEF or automatically after 1000 ms to limit the maximum of time the UI is allowed to keep the user waiting.
The wrong order of events can lead to race conditions and has already led to obscure crashes that occur because the state of the underlying objects while the
closeBrowserfunction is executed have been in semi-invalid states and pointers have become invalid seemingly at random on users' machines.How Has This Been Tested?
Tested on Windows and macOS, successfully establishing service connections and aborting the attempt to establish one, checking that the associated OAuth panels are correctly closed up.
Also checked with custom browser panels.
This change also hardens the code responsible to remove the
NSViewfrom the window hierarchy before the browser is closed by explicitly checking if the instance the ObjC messages are being sent to still has the requiredisapointer to make it an ObjC class instance.The associated code has been moved into a separate function as it should be implemented in a platform-specific ObjC file instead (so ObjC functions can be called directly) instead of being interweaved with code for other platforms via preprocessor conditions.
Types of changes
Checklist:
Replaced the
reinterpret_castused by original code with the safer, and more correct,static_castvariant.While
dynamic_castwould be the absolutely correct choice as it will just return anullptrif the pointer to the base class cannot correctly be downcast to the derived class, there is currently no way the pointer returned byhost->GetClient()in this part of the code will return a client that is not aQCefBrowserClient. Thusstatic_castis good-enough.