Description
Preflight Checklist
- I have read the Contributing Guidelines for this project.
- I agree to follow the Code of Conduct that this project adheres to.
- I have searched the issue tracker for a bug report that matches the one I want to file, without success.
Electron Version
30.0.0
What operating system are you using?
Windows
Operating System Version
Windows 10 & 11
What arch are you using?
x64
Last Known Working Electron version
22.0.0
Expected Behavior
The Electron window contents should not disappear after several minutes when using the background throttling feature.
Actual Behavior
Reproduce steps:
- Run the Electron Fiddle project in the gist url provided
- Open the devtools and popout into separate window (this doesn't change the behavior but is needed to invoke the disabling of background throttling)
- Minimize the main electron window
- In the devtools console run
electronApp.disableBackgroundThrottling();
- Restore the main electron window
- Wait 5-10 minutes (usually 10), window contents will incorrectly go blank
- Observe that moving the mouse around will still change the cursor, devtools will still show a valid DOM
This reproduces on Windows, have not tried on other OSes.
Note: Resizing the window or minimizing/restoring will temporarily fix the behavior and show the contents, but after the 5-10 minute window the contents will go blank again.
Testcase Gist URL
https://gist.github.com/markh-discord/4d828931b38d5917e5c8e73101981a54
Additional Information
This appears to be a bug with the disable_hidden.patch
:
Note: When background throttling is enabled (default), the disable_hidden_
state will be false
.
From the reproduce steps, when the window is minimized (which calls RenderWidgetHostViewAura::HideImpl()
) the condition above passes and eventually calls into:
delegated_frame_host_->WasHidden(cause);
which calls:
frame_evictor_->SetVisible(false);
The next step is to disable the background throttling, effectively setting disable_hidden_
to true
.
This triggers the RenderWidgetHostImpl::WasShown
since it's currently hidden and sets is_hidden_ = true
:
Note that at this point the window is still minimized and not visibly shown to the user.
The next step is then to restore the window, this then hits this code (linking to the patch here since that's effectively what it's running):
This condition now fails because the
host_->is_hidden()
was toggled above to true
, skipping the calls to:
RenderWidgetHostViewBase::OnShowWithPageVisibility
RenderWidgetHostViewAura::NotifyHostAndDelegateOnWasShown
DelegatedFrameHost::WasShown
FrameEvictor::SetVisible(true)
Since this entire runtime path is skipped, the FrameEvictor
attached to the DelegatedFrameHost
(which is attached to the RenderWidgetHost) believes it's still not visible.
The FrameEvictorManager
has a 5 minute timer where it will begin evicting frames it believes aren't seen:
static constexpr base::TimeDelta kPeriodicCullingDelay = base::Minutes(5);
https://chromium.googlesource.com/chromium/src.git/+/27caf432b8c27240dd42820a7c5e098374a91970/components/viz/client/frame_eviction_manager.h#90
The timer gets setup here with the 5 minute delay: https://chromium.googlesource.com/chromium/src.git/+/27caf432b8c27240dd42820a7c5e098374a91970/components/viz/client/frame_eviction_manager.cc#88
Likely due to small timing differences after the timer runs, the 5 minutes hasn't quite been hit in the check here:
https://chromium.googlesource.com/chromium/src.git/+/27caf432b8c27240dd42820a7c5e098374a91970/components/viz/client/frame_eviction_manager.cc#183
So it must wait another 5 minutes before the timer ticks again, which usually results in the 10 minute wait needed to observe this problem.
We did not see this behavior in Electron 22, but noticed it in Electron 28. This doesn't seem to be a problem in Electron 22 since the FrameEvictor was disabled at that point in time and was enabled shortly after: https://chromium.googlesource.com/chromium/src.git/+/4fbc6d67f7ba71ed61bedac5a146d3d931aba4c1