Skip to content

Fix CEF browser startup hang and make failed webcore init clean up after itself - #5321

Draft
Dutchman101 wants to merge 2 commits into
multitheftauto:masterfrom
Dutchman101:cef-init-1
Draft

Fix CEF browser startup hang and make failed webcore init clean up after itself#5321
Dutchman101 wants to merge 2 commits into
multitheftauto:masterfrom
Dutchman101:cef-init-1

Conversation

@Dutchman101

@Dutchman101 Dutchman101 commented Sep 5, 2026

Copy link
Copy Markdown
Member

This PR improves how CEF initializes.
A long game freeze was observed on some machines (20+ seconds isn't unusual).

Why

  • On Windows 11 22H2 and newer, opening the first in-game browser could stall the game thread for a long time. Chromium was downgrading its background renderer processes to a power-saving "EcoQoS" mode, and that call path is slow. We now tell Chromium not to do that downgrade, which removes the stall. Older Windows versions are unaffected.

  • If browser initialization failed partway, the game was left in a half-broken state: the process-wide DLL search path stayed changed, and some failures weren't reported properly. This makes troubleshooting and recovery much harder than it needs to be.

What changed (all in CWebApp.cpp and CWebCore.cpp):

  1. Added --disable-renderer-backgrounding to the CEF command line to prevent the first-browser stall described above.
    When CEF init fails, the previous DLL search directory is now restored (via a small save/restore guard). On success the CEF directory stays set, because CEF loads its DLLs on demand after startup.

  2. SetDllDirectoryW is now checked, and if it fails we fail closed with report code 8032 instead of continuing into a broken state.
    Scheme handler registration now fails cleanly if it throws (8030) or returns false (8031), instead of running with broken mta:// pages.

  3. A CefInitialize throw now reports only 8003, and a false return only 8004 (they used to double-report).
    The "failed to change working directory" error got its own report code (8029); it was previously sharing 8026 with the Wine/Proton error.

Trade-off
Hidden background browsers will now keep normal priority instead of best-effort, which can slightly raise idle CPU usage when many browser views are open. I consider the freeze on first browser open to be the worse problem.

Comment on lines +130 to +131
while (!previousDllDir.empty() && previousDllDir.back() == L'\0')
previousDllDir.pop_back();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetDllDirectoryW returns the length of the path excluding the terminating null character, so resize(got) is sufficient here and avoids manually removing trailing null characters.

if (restore && known)
SetDllDirectoryW(dir.empty() ? nullptr : dir.c_str());
}
} dllDirGuard(std::move(previousDllDir), previousDllDirKnown);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use std::scope_exit here instead of the custom DllDirGuard? Since we're using C++23, this would give us the same RAII based rollback behavior with less code. We can call release() after successful initialization so the CEF DLL directory remains active, while all failure paths automatically restore the previous directory.

Comment thread Client/cefweb/CWebApp.cpp
// 144 applies EcoQoS from SetPriority() without a feature gate, and
// this switch is the only one that prevents the downgrade, so do not
// replace it with a disable-features entry.
commandLine->AppendSwitch("disable-renderer-backgrounding");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question is how much CPU usage will increase after disabling EcoQoS? Perhaps it would be worth keeping it as an option that can be enabled in the settings? If the difference is significant, it could be useful for laptop users.

@Dutchman101
Dutchman101 marked this pull request as draft September 5, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants