Cherry pick PR #9798: Cobalt: Fix application lifecycle and focus reporting issues#10011
Merged
Cherry pick PR #9798: Cobalt: Fix application lifecycle and focus reporting issues#10011
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as off-topic.
This comment was marked as off-topic.
fecba7c to
96e0a65
Compare
This comment was marked as resolved.
This comment was marked as resolved.
This PR significantly hardens the Cobalt application lifecycle, specifically addressing synchronous blocking requirements during downward state transitions and improving the robustness of the message pump for nested loops. * **MessagePumpUIStarboard nested loop support:** Implemented the previously missing `Run()` method (which formerly threw a `NOTREACHED()`) to support a full Chromium-style message loop. This is critical for enabling nested `base::RunLoop` calls, allowing the main OS thread to block during teardown while the UI thread continues to process asynchronous tasks (e.g., surface destruction). The loop blocks highly efficiently using `base::WaitableEvent::TimedWait()`. * **Synchronous State Transitions:** Refactored `AppEventDelegate` to explicitly block the Starboard OS thread during downward transitions (Blur, Conceal, Freeze) until the target state is reached and all asynchronous side effects are completed. This uses a nested `RunLoop` on the UI thread and dynamically instantiated `WaitableEvent`s on non-UI threads. Added a 5-second safety timeout (`kTransitionTimeout`) to prevent permanent Starboard thread hangs. * **Stability & Thread Safety:** * **Deadlock Prevention:** The final `kStopped` state transition (which destroys the `SequenceManager`) is now safely executed *synchronously* outside of the nested `RunLoop`. Attempting to tear down the task queue from within one of its own tasks would cause a fatal deadlock. * Replaced `ContentMain` with `RunContentProcess` using a process-lifetime static `ContentMainRunner` to resolve SIGSEGV issues during shutdown. * Introduced `base::Lock` and `std::atomic` state variables in `AppEventDelegate` and `AppEventRunner` to serialize lifecycle event processing and ensure thread safety across multiple threads without lock contention. * Improved `MessagePumpUIStarboard` destruction (calling `CancelAll()` and `AfterRun()`) to prevent `DCHECK` crashes in `SequenceManager` during teardown. * **Visibility & Focus Reporting:** * Added explicit calls to `web_contents()->WasHidden()` and `WasShown()` in `ShellPlatformDelegate` to ensure the compositor and Aura correctly track visibility changes. * **Deterministic Focus:** Implemented a robust focus deferral mechanism in `cobalt::Shell`. Focus requests arriving while the window is hidden are queued and applied precisely when Aura signals visibility via `OnVisibilityChanged`. * **Robust Integration Tests:** Rewrote `test_lifecycle.sh` and `test_preload.sh` to include precise process cleanup validation (handling zombie states) and a new `wait_for_state.sh` helper that polls for JS state via DevTools, eliminating race conditions previously handled by brittle `sleep` commands. Bug: 492166511 Bug: 491841704 Bug: 475990372 Bug: 477170017 Bug: 474496110 Bug: 492693465 Bug: 494002968 (cherry picked from commit 93935f0)
96e0a65 to
5e0d2ed
Compare
jellefoks
approved these changes
Apr 15, 2026
andrewsavage1
approved these changes
Apr 15, 2026
cobalt-github-releaser-bot
added a commit
that referenced
this pull request
Apr 15, 2026
…lifecycle and focus reporting issues Refer to original PR: #10011 Refer to the original PR: #9798 This PR significantly hardens the Cobalt application lifecycle, specifically addressing synchronous blocking requirements during downward state transitions and improving the robustness of the message pump for nested loops. #### Key Improvements * **MessagePumpUIStarboard nested loop support:** Implemented the previously missing `Run()` method (which formerly threw a `NOTREACHED()`) to support a full Chromium-style message loop. This is critical for enabling nested `base::RunLoop` calls, allowing the main OS thread to block during teardown while the UI thread continues to process asynchronous tasks (e.g., surface destruction). The loop blocks highly efficiently using `base::WaitableEvent::TimedWait()`. * **Synchronous State Transitions:** Refactored `AppEventDelegate` to explicitly block the Starboard OS thread during downward transitions (Blur, Conceal, Freeze) until the target state is reached and all asynchronous side effects are completed. This uses a nested `RunLoop` on the UI thread and dynamically instantiated `WaitableEvent`s on non-UI threads. Added a 5-second safety timeout (`kTransitionTimeout`) to prevent permanent Starboard thread hangs. * **Stability & Thread Safety:** * **Deadlock Prevention:** The final `kStopped` state transition (which destroys the `SequenceManager`) is now safely executed *synchronously* outside of the nested `RunLoop`. Attempting to tear down the task queue from within one of its own tasks would cause a fatal deadlock. * Replaced `ContentMain` with `RunContentProcess` using a process-lifetime static `ContentMainRunner` to resolve SIGSEGV issues during shutdown. * Introduced `base::Lock` and `std::atomic` state variables in `AppEventDelegate` and `AppEventRunner` to serialize lifecycle event processing and ensure thread safety across multiple threads without lock contention. * Improved `MessagePumpUIStarboard` destruction (calling `CancelAll()` and `AfterRun()`) to prevent `DCHECK` crashes in `SequenceManager` during teardown. * **Visibility & Focus Reporting:** * Added explicit calls to `web_contents()->WasHidden()` and `WasShown()` in `ShellPlatformDelegate` to ensure the compositor and Aura correctly track visibility changes. * **Deterministic Focus:** Implemented a robust focus deferral mechanism in `cobalt::Shell`. Focus requests arriving while the window is hidden are queued and applied precisely when Aura signals visibility via `OnVisibilityChanged`. * **Robust Integration Tests:** Rewrote `test_lifecycle.sh` and `test_preload.sh` to include precise process cleanup validation (handling zombie states) and a new `wait_for_state.sh` helper that polls for JS state via DevTools, eliminating race conditions previously handled by brittle `sleep` commands. Bug: 492166511 Bug: 491841704 Bug: 475990372 Bug: 477170017 Bug: 474496110 Bug: 492693465 Bug: 494002968 Co-authored-by: Jelle Foks <jfoks@google.com> (cherry picked from commit a793a7c)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refer to the original PR: #9798
This PR significantly hardens the Cobalt application lifecycle, specifically addressing synchronous blocking requirements during downward state transitions and improving the robustness of the message pump for nested loops.
Key Improvements
Run()method (which formerly threw aNOTREACHED()) to support a full Chromium-style message loop. This is critical for enabling nestedbase::RunLoopcalls, allowing the main OS thread to block during teardown while the UI thread continues to process asynchronous tasks (e.g., surface destruction). The loop blocks highly efficiently usingbase::WaitableEvent::TimedWait().AppEventDelegateto explicitly block the Starboard OS thread during downward transitions (Blur, Conceal, Freeze) until the target state is reached and all asynchronous side effects are completed. This uses a nestedRunLoopon the UI thread and dynamically instantiatedWaitableEvents on non-UI threads. Added a 5-second safety timeout (kTransitionTimeout) to prevent permanent Starboard thread hangs.kStoppedstate transition (which destroys theSequenceManager) is now safely executed synchronously outside of the nestedRunLoop. Attempting to tear down the task queue from within one of its own tasks would cause a fatal deadlock.ContentMainwithRunContentProcessusing a process-lifetime staticContentMainRunnerto resolve SIGSEGV issues during shutdown.base::Lockandstd::atomicstate variables inAppEventDelegateandAppEventRunnerto serialize lifecycle event processing and ensure thread safety across multiple threads without lock contention.MessagePumpUIStarboarddestruction (callingCancelAll()andAfterRun()) to preventDCHECKcrashes inSequenceManagerduring teardown.web_contents()->WasHidden()andWasShown()inShellPlatformDelegateto ensure the compositor and Aura correctly track visibility changes.cobalt::Shell. Focus requests arriving while the window is hidden are queued and applied precisely when Aura signals visibility viaOnVisibilityChanged.test_lifecycle.shandtest_preload.shto include precise process cleanup validation (handling zombie states) and a newwait_for_state.shhelper that polls for JS state via DevTools, eliminating race conditions previously handled by brittlesleepcommands.Bug: 492166511
Bug: 491841704
Bug: 475990372
Bug: 477170017
Bug: 474496110
Bug: 492693465
Bug: 494002968