windows: Configure stack size for executables (fixes issue #3250)

Change the default stack size to 8 MiB for 64-bit and 0.5 MiB for 32-bit.

CEF's main thread needs at least a 1.5 MiB stack size in order to avoid
stack overflow crashes. However, if this is set in the PE file then other
threads get this size as well, leading to address-space exhaustion in 32-bit
CEF. A new CefRunWinMainWithPreferredStackSize function uses fibers to switch
the main thread to a 4 MiB stack (roughly the same effective size as the
64-bit build's 8 MiB stack) before running any other code.

This change additionally moves the existing Windows-only functions
CefSetOSModalLoop and CefEnableHighDPISupport from cef_app.h to cef_win.h.
This commit is contained in:
Marshall Greenblatt 2022-10-20 18:23:32 -04:00
parent dfd1917d9b
commit 07bf5dbacc
20 changed files with 482 additions and 92 deletions

View File

@ -1210,6 +1210,21 @@ config("libcef_dll_wrapper_config") {
] ]
configs = [ ":libcef_autogen_config" ] configs = [ ":libcef_autogen_config" ]
if (is_win) {
if (current_cpu == "x86") {
# Set the initial stack size to 0.5MiB, instead of the 1.5MiB minimum
# needed by CEF's main thread. This saves significant memory on threads
# (like those in the Windows thread pool, and others) whose stack size we
# can only control through this setting. The main thread (in 32-bit builds
# only) uses fibers to switch to a 4MiB stack at runtime via
# CefRunWinMainWithPreferredStackSize().
ldflags = [ "/STACK:0x80000" ]
} else {
# Increase the initial stack size to 8MiB from the default 1MiB.
ldflags = [ "/STACK:0x800000" ]
}
}
} }
# libcef_dll_wrapper target. # libcef_dll_wrapper target.

View File

@ -2375,7 +2375,8 @@ PREDEFINED = USING_CEF_SHARED \
OS_WIN \ OS_WIN \
OS_LINUX \ OS_LINUX \
CEF_X11 \ CEF_X11 \
OS_MAC OS_MAC \
ARCH_CPU_32_BITS
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The # tag can be used to specify a list of macro names that should be expanded. The

View File

@ -79,6 +79,7 @@
'include/internal/cef_win.h', 'include/internal/cef_win.h',
], ],
'includes_win_capi': [ 'includes_win_capi': [
'include/internal/cef_app_win.h',
'include/internal/cef_types_win.h', 'include/internal/cef_types_win.h',
], ],
'includes_mac': [ 'includes_mac': [

View File

@ -448,6 +448,23 @@ if(OS_WINDOWS)
NDEBUG _NDEBUG # Not a debug build NDEBUG _NDEBUG # Not a debug build
) )
if(PROJECT_ARCH STREQUAL "x86")
# Set the initial stack size to 0.5MiB, instead of the 1.5MiB minimum
# needed by CEF's main thread. This saves significant memory on threads
# (like those in the Windows thread pool, and others) whose stack size we
# can only control through this setting. The main thread (in 32-bit builds
# only) uses fibers to switch to a 4MiB stack at runtime via
# CefRunWinMainWithPreferredStackSize().
list(APPEND CEF_EXE_LINKER_FLAGS
/STACK:0x8000
)
else()
# Increase the initial stack size to 8MiB from the default 1MiB.
list(APPEND CEF_EXE_LINKER_FLAGS
/STACK:0x800000
)
endif()
# Standard libraries. # Standard libraries.
set(CEF_STANDARD_LIBS set(CEF_STANDARD_LIBS
comctl32.lib comctl32.lib

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for // by hand. See the translator.README.txt file in the tools directory for
// more information. // more information.
// //
// $hash=7c6894aae3e508aaa42a376532328316d9bd509c$ // $hash=2f4bdc6adde5defdc86dbb5c998266d6372dd164$
// //
#ifndef CEF_INCLUDE_CAPI_CEF_APP_CAPI_H_ #ifndef CEF_INCLUDE_CAPI_CEF_APP_CAPI_H_
@ -183,19 +183,6 @@ CEF_EXPORT void cef_run_message_loop(void);
/// ///
CEF_EXPORT void cef_quit_message_loop(void); CEF_EXPORT void cef_quit_message_loop(void);
///
/// Set to true (1) before calling Windows APIs like TrackPopupMenu that enter a
/// modal message loop. Set to false (0) after exiting the modal message loop.
///
CEF_EXPORT void cef_set_osmodal_loop(int osModalLoop);
///
/// Call during process startup to enable High-DPI support on Windows 7 or
/// newer. Older versions of Windows should be left DPI-unaware because they do
/// not support DirectWrite and GDI fonts are kerned very badly.
///
CEF_EXPORT void cef_enable_highdpi_support(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -42,13 +42,13 @@
// way that may cause binary incompatibility with other builds. The universal // way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash // hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected. // values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "b52718166004e2be9d225454b9999445e1a5d131" #define CEF_API_HASH_UNIVERSAL "6d1cae87bcec7d95d2a6415ced3101dcfd59381b"
#if defined(OS_WIN) #if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "f327210f819821b0f53a9071281622e16c8515bd" #define CEF_API_HASH_PLATFORM "00cf5307a1868e22a8672a4904455ff908b14f9c"
#elif defined(OS_MAC) #elif defined(OS_MAC)
#define CEF_API_HASH_PLATFORM "41b7d845bec3d93f820e6e940583085351fda410" #define CEF_API_HASH_PLATFORM "f55dd87087c511892883aacd0e55a433f6a04588"
#elif defined(OS_LINUX) #elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "fd19a4db781e699f7b2492f9fc2c63544934a6e4" #define CEF_API_HASH_PLATFORM "b7e663de88e1af8e8b775f8699463bae6c0d9a0a"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -123,21 +123,6 @@ void CefRunMessageLoop();
/*--cef()--*/ /*--cef()--*/
void CefQuitMessageLoop(); void CefQuitMessageLoop();
///
/// Set to true before calling Windows APIs like TrackPopupMenu that enter a
/// modal message loop. Set to false after exiting the modal message loop.
///
/*--cef()--*/
void CefSetOSModalLoop(bool osModalLoop);
///
/// Call during process startup to enable High-DPI support on Windows 7 or
/// newer. Older versions of Windows should be left DPI-unaware because they do
/// not support DirectWrite and GDI fonts are kerned very badly.
///
/*--cef(capi_name=cef_enable_highdpi_support)--*/
void CefEnableHighDPISupport();
/// ///
/// Implement this interface to provide handler implementations. Methods will be /// Implement this interface to provide handler implementations. Methods will be
/// called by the process and/or thread indicated. /// called by the process and/or thread indicated.

View File

@ -0,0 +1,107 @@
// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CEF_INCLUDE_INTERNAL_CEF_APP_WIN_H_
#define CEF_INCLUDE_INTERNAL_CEF_APP_WIN_H_
#pragma once
#include "include/base/cef_build.h"
#if defined(OS_WIN)
#if defined(ARCH_CPU_32_BITS)
#include <windows.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(ARCH_CPU_32_BITS)
typedef int(APIENTRY* wWinMainPtr)(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nCmdShow);
typedef int (*mainPtr)(int argc, char* argv[]);
///
/// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
/// stack size. This function must be called at the top of the executable entry
/// point function (`main()` or `wWinMain()`). It is used in combination with
/// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
/// flag on executable targets. This saves significant memory on threads (like
/// those in the Windows thread pool, and others) whose stack size can only be
/// controlled via the linker flag.
///
/// CEF's main thread needs at least a 1.5 MiB stack size in order to avoid
/// stack overflow crashes. However, if this is set in the PE file then other
/// threads get this size as well, leading to address-space exhaustion in 32-bit
/// CEF. This function uses fibers to switch the main thread to a 4 MiB stack
/// (roughly the same effective size as the 64-bit build's 8 MiB stack) before
/// running any other code.
///
/// Choose the function variant that matches the entry point function type used
/// by the executable. Reusing the entry point minimizes confusion when
/// examining call stacks in crash reports.
///
/// If this function is already running on the fiber it will return -1
/// immediately, meaning that execution should proceed with the remainder of the
/// entry point function. Otherwise, this function will block until the entry
/// point function has completed execution on the fiber and then return a result
/// >= 0, meaning that the entry point function should return the result
/// immediately without proceeding with execution.
///
CEF_EXPORT int cef_run_winmain_with_preferred_stack_size(wWinMainPtr wWinMain,
HINSTANCE hInstance,
LPWSTR lpCmdLine,
int nCmdShow);
CEF_EXPORT int cef_run_main_with_preferred_stack_size(mainPtr main,
int argc,
char* argv[]);
#endif // defined(ARCH_CPU_32_BITS)
///
/// Call during process startup to enable High-DPI support on Windows 7 or
/// newer. Older versions of Windows should be left DPI-unaware because they do
/// not support DirectWrite and GDI fonts are kerned very badly.
///
CEF_EXPORT void cef_enable_highdpi_support(void);
///
/// Set to true (1) before calling Windows APIs like TrackPopupMenu that enter a
/// modal message loop. Set to false (0) after exiting the modal message loop.
///
CEF_EXPORT void cef_set_osmodal_loop(int osModalLoop);
#ifdef __cplusplus
}
#endif
#endif // defined(OS_WIN)
#endif // CEF_INCLUDE_INTERNAL_CEF_APP_WIN_H_

View File

@ -31,6 +31,7 @@
#define CEF_INCLUDE_INTERNAL_CEF_WIN_H_ #define CEF_INCLUDE_INTERNAL_CEF_WIN_H_
#pragma once #pragma once
#include "include/internal/cef_app_win.h"
#include "include/internal/cef_types_win.h" #include "include/internal/cef_types_win.h"
#include "include/internal/cef_types_wrappers.h" #include "include/internal/cef_types_wrappers.h"
@ -132,4 +133,52 @@ class CefWindowInfo : public CefStructBase<CefWindowInfoTraits> {
} }
}; };
#if defined(ARCH_CPU_32_BITS)
///
/// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
/// stack size. This function must be called at the top of the executable entry
/// point function (`main()` or `wWinMain()`). It is used in combination with
/// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
/// flag on executable targets. This saves significant memory on threads (like
/// those in the Windows thread pool, and others) whose stack size can only be
/// controlled via the linker flag.
///
/// CEF's main thread needs at least a 1.5 MiB stack size in order to avoid
/// stack overflow crashes. However, if this is set in the PE file then other
/// threads get this size as well, leading to address-space exhaustion in 32-bit
/// CEF. This function uses fibers to switch the main thread to a 4 MiB stack
/// (roughly the same effective size as the 64-bit build's 8 MiB stack) before
/// running any other code.
///
/// Choose the function variant that matches the entry point function type used
/// by the executable. Reusing the entry point minimizes confusion when
/// examining call stacks in crash reports.
///
/// If this function is already running on the fiber it will return -1
/// immediately, meaning that execution should proceed with the remainder of the
/// entry point function. Otherwise, this function will block until the entry
/// point function has completed execution on the fiber and then return a result
/// >= 0, meaning that the entry point function should return the result
/// immediately without proceeding with execution.
///
int CefRunWinMainWithPreferredStackSize(wWinMainPtr wWinMain,
HINSTANCE hInstance,
LPWSTR lpCmdLine,
int nCmdShow);
int CefRunMainWithPreferredStackSize(mainPtr main, int argc, char* argv[]);
#endif // defined(ARCH_CPU_32_BITS)
///
/// Call during process startup to enable High-DPI support on Windows 7 or
/// newer. Older versions of Windows should be left DPI-unaware because they do
/// not support DirectWrite and GDI fonts are kerned very badly.
///
void CefEnableHighDPISupport();
///
/// Set to true before calling Windows APIs like TrackPopupMenu that enter a
/// modal message loop. Set to false after exiting the modal message loop.
///
void CefSetOSModalLoop(bool osModalLoop);
#endif // CEF_INCLUDE_INTERNAL_CEF_WIN_H_ #endif // CEF_INCLUDE_INTERNAL_CEF_WIN_H_

View File

@ -21,9 +21,12 @@
#include "ui/base/ui_base_switches.h" #include "ui/base/ui_base_switches.h"
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
#include "base/debug/alias.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/win/win_util.h"
#include "chrome/chrome_elf/chrome_elf_main.h" #include "chrome/chrome_elf/chrome_elf_main.h"
#include "chrome/install_static/initialize_from_primary_module.h" #include "chrome/install_static/initialize_from_primary_module.h"
#include "include/internal/cef_win.h"
#endif #endif
namespace { namespace {
@ -158,6 +161,110 @@ base::FilePath NormalizeCachePathAndSet(cef_string_t& path_str,
return path; return path;
} }
// Based on chrome/app/chrome_exe_main_win.cc.
// In 32-bit builds, the main thread starts with the default (small) stack size.
// The ARCH_CPU_32_BITS blocks here and below are in support of moving the main
// thread to a fiber with a larger stack size.
#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_32_BITS)
// The information needed to transfer control to the large-stack fiber and later
// pass the main routine's exit code back to the small-stack fiber prior to
// termination.
struct FiberState {
FiberState(wWinMainPtr wWinMain,
HINSTANCE hInstance,
LPWSTR lpCmdLine,
int nCmdShow) {
this->wWinMain = wWinMain;
this->hInstance = hInstance;
this->lpCmdLine = lpCmdLine;
this->nCmdShow = nCmdShow;
}
FiberState(mainPtr main, int argc, char** argv) {
this->main = main;
this->argc = argc;
this->argv = argv;
}
wWinMainPtr wWinMain = nullptr;
HINSTANCE hInstance;
LPWSTR lpCmdLine;
int nCmdShow;
mainPtr main = nullptr;
int argc;
char** argv;
LPVOID original_fiber;
int fiber_result;
};
// A PFIBER_START_ROUTINE function run on a large-stack fiber that calls the
// main routine, stores its return value, and returns control to the small-stack
// fiber. |params| must be a pointer to a FiberState struct.
void WINAPI FiberBinder(void* params) {
auto* fiber_state = static_cast<FiberState*>(params);
// Call the main routine from the fiber. Reusing the entry point minimizes
// confusion when examining call stacks in crash reports - seeing wWinMain on
// the stack is a handy hint that this is the main thread of the process.
if (fiber_state->main) {
fiber_state->fiber_result =
fiber_state->main(fiber_state->argc, fiber_state->argv);
} else {
fiber_state->fiber_result =
fiber_state->wWinMain(fiber_state->hInstance, nullptr,
fiber_state->lpCmdLine, fiber_state->nCmdShow);
}
// Switch back to the main thread to exit.
::SwitchToFiber(fiber_state->original_fiber);
}
int RunMainWithPreferredStackSize(FiberState& fiber_state) {
enum class FiberStatus { kConvertFailed, kCreateFiberFailed, kSuccess };
FiberStatus fiber_status = FiberStatus::kSuccess;
// GetLastError result if fiber conversion failed.
DWORD fiber_error = ERROR_SUCCESS;
if (!::IsThreadAFiber()) {
// Make the main thread's stack size 4 MiB so that it has roughly the same
// effective size as the 64-bit build's 8 MiB stack.
constexpr size_t kStackSize = 4 * 1024 * 1024; // 4 MiB
// Leak the fiber on exit.
LPVOID original_fiber =
::ConvertThreadToFiberEx(nullptr, FIBER_FLAG_FLOAT_SWITCH);
if (original_fiber) {
fiber_state.original_fiber = original_fiber;
// Create a fiber with a bigger stack and switch to it. Leak the fiber on
// exit.
LPVOID big_stack_fiber = ::CreateFiberEx(
0, kStackSize, FIBER_FLAG_FLOAT_SWITCH, FiberBinder, &fiber_state);
if (big_stack_fiber) {
::SwitchToFiber(big_stack_fiber);
// The fibers must be cleaned up to avoid obscure TLS-related shutdown
// crashes.
::DeleteFiber(big_stack_fiber);
::ConvertFiberToThread();
// Control returns here after CEF has finished running on FiberMain.
return fiber_state.fiber_result;
}
fiber_status = FiberStatus::kCreateFiberFailed;
} else {
fiber_status = FiberStatus::kConvertFailed;
}
// If we reach here then creating and switching to a fiber has failed. This
// probably means we are low on memory and will soon crash. Try to report
// this error once crash reporting is initialized.
fiber_error = ::GetLastError();
base::debug::Alias(&fiber_error);
}
// If we are already a fiber then continue normal execution.
// Intentionally crash if converting to a fiber failed.
CHECK_EQ(fiber_status, FiberStatus::kSuccess);
return -1;
}
#endif // BUILDFLAG(IS_WIN) && defined(ARCH_CPU_32_BITS)
} // namespace } // namespace
int CefExecuteProcess(const CefMainArgs& args, int CefExecuteProcess(const CefMainArgs& args,
@ -268,8 +375,30 @@ void CefQuitMessageLoop() {
g_context->QuitMessageLoop(); g_context->QuitMessageLoop();
} }
void CefSetOSModalLoop(bool osModalLoop) {
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
#if defined(ARCH_CPU_32_BITS)
int CefRunWinMainWithPreferredStackSize(wWinMainPtr wWinMain,
HINSTANCE hInstance,
LPWSTR lpCmdLine,
int nCmdShow) {
CHECK(wWinMain && hInstance);
FiberState fiber_state(wWinMain, hInstance, lpCmdLine, nCmdShow);
return RunMainWithPreferredStackSize(fiber_state);
}
int CefRunMainWithPreferredStackSize(mainPtr main, int argc, char* argv[]) {
CHECK(main);
FiberState fiber_state(main, argc, argv);
return RunMainWithPreferredStackSize(fiber_state);
}
#endif // defined(ARCH_CPU_32_BITS)
void CefEnableHighDPISupport() {
base::win::EnableHighDPISupport();
}
void CefSetOSModalLoop(bool osModalLoop) {
// Verify that the context is in a valid state. // Verify that the context is in a valid state.
if (!CONTEXT_STATE_VALID()) { if (!CONTEXT_STATE_VALID()) {
NOTREACHED() << "context not valid"; NOTREACHED() << "context not valid";
@ -282,9 +411,10 @@ void CefSetOSModalLoop(bool osModalLoop) {
} }
base::CurrentThread::Get()->set_os_modal_loop(osModalLoop); base::CurrentThread::Get()->set_os_modal_loop(osModalLoop);
#endif // BUILDFLAG(IS_WIN)
} }
#endif // BUILDFLAG(IS_WIN)
// CefContext // CefContext
CefContext::CefContext() CefContext::CefContext()

View File

@ -12,10 +12,6 @@
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#if BUILDFLAG(IS_WIN)
#include "base/win/win_util.h"
#endif
namespace { namespace {
constexpr const char kCategory[] = "cef.client"; constexpr const char kCategory[] = "cef.client";
@ -334,9 +330,3 @@ cef_get_current_platform_thread_handle() {
return base::PlatformThread::CurrentHandle().platform_handle(); return base::PlatformThread::CurrentHandle().platform_handle();
#endif #endif
} }
void CefEnableHighDPISupport() {
#if BUILDFLAG(IS_WIN)
base::win::EnableHighDPISupport();
#endif
}

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory // implementations. See the translator.README.txt file in the tools directory
// for more information. // for more information.
// //
// $hash=a3be9b3f96ebf8c8840856a6f454729d77459a22$ // $hash=6bc0085b04e78068511eb7198a3f9bda103adc85$
// //
#include "include/capi/cef_app_capi.h" #include "include/capi/cef_app_capi.h"
@ -146,20 +146,6 @@ CEF_EXPORT void cef_quit_message_loop() {
CefQuitMessageLoop(); CefQuitMessageLoop();
} }
CEF_EXPORT void cef_set_osmodal_loop(int osModalLoop) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
CefSetOSModalLoop(osModalLoop ? true : false);
}
CEF_EXPORT void cef_enable_highdpi_support() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
CefEnableHighDPISupport();
}
CEF_EXPORT int cef_crash_reporting_enabled() { CEF_EXPORT int cef_crash_reporting_enabled() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

View File

@ -4,9 +4,15 @@
// //
#include <cstddef> #include <cstddef>
#include "include/base/cef_build.h"
#include "include/cef_api_hash.h" #include "include/cef_api_hash.h"
#include "include/cef_version.h" #include "include/cef_version.h"
#if defined(OS_WIN)
#include "include/internal/cef_win.h"
#endif
CEF_EXPORT int cef_version_info(int entry) { CEF_EXPORT int cef_version_info(int entry) {
switch (entry) { switch (entry) {
case 0: case 0:
@ -42,3 +48,31 @@ CEF_EXPORT const char* cef_api_hash(int entry) {
return NULL; return NULL;
} }
} }
#if defined(OS_WIN)
#if defined(ARCH_CPU_32_BITS)
CEF_EXPORT int cef_run_winmain_with_preferred_stack_size(wWinMainPtr wWinMain,
HINSTANCE hInstance,
LPWSTR lpCmdLine,
int nCmdShow) {
return CefRunWinMainWithPreferredStackSize(wWinMain, hInstance, lpCmdLine,
nCmdShow);
}
CEF_EXPORT int cef_run_main_with_preferred_stack_size(mainPtr main,
int argc,
char* argv[]) {
return CefRunMainWithPreferredStackSize(main, argc, argv);
}
#endif // defined(ARCH_CPU_32_BITS)
CEF_EXPORT void cef_enable_highdpi_support() {
CefEnableHighDPISupport();
}
CEF_EXPORT void cef_set_osmodal_loop(int osModalLoop) {
CefSetOSModalLoop(osModalLoop ? true : false);
}
#endif // defined(OS_WIN)

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory // implementations. See the translator.README.txt file in the tools directory
// for more information. // for more information.
// //
// $hash=bb6f61b0d69253de7bcc5506fd04562e46fa797c$ // $hash=b5dc1bb07ea5cbf057bf40491fdcdddeb58dfa57$
// //
#include <dlfcn.h> #include <dlfcn.h>
@ -95,8 +95,6 @@ struct libcef_pointers {
decltype(&cef_do_message_loop_work) cef_do_message_loop_work; decltype(&cef_do_message_loop_work) cef_do_message_loop_work;
decltype(&cef_run_message_loop) cef_run_message_loop; decltype(&cef_run_message_loop) cef_run_message_loop;
decltype(&cef_quit_message_loop) cef_quit_message_loop; decltype(&cef_quit_message_loop) cef_quit_message_loop;
decltype(&cef_set_osmodal_loop) cef_set_osmodal_loop;
decltype(&cef_enable_highdpi_support) cef_enable_highdpi_support;
decltype(&cef_crash_reporting_enabled) cef_crash_reporting_enabled; decltype(&cef_crash_reporting_enabled) cef_crash_reporting_enabled;
decltype(&cef_set_crash_key_value) cef_set_crash_key_value; decltype(&cef_set_crash_key_value) cef_set_crash_key_value;
decltype(&cef_create_directory) cef_create_directory; decltype(&cef_create_directory) cef_create_directory;
@ -336,8 +334,6 @@ int libcef_init_pointers(const char* path) {
INIT_ENTRY(cef_do_message_loop_work); INIT_ENTRY(cef_do_message_loop_work);
INIT_ENTRY(cef_run_message_loop); INIT_ENTRY(cef_run_message_loop);
INIT_ENTRY(cef_quit_message_loop); INIT_ENTRY(cef_quit_message_loop);
INIT_ENTRY(cef_set_osmodal_loop);
INIT_ENTRY(cef_enable_highdpi_support);
INIT_ENTRY(cef_crash_reporting_enabled); INIT_ENTRY(cef_crash_reporting_enabled);
INIT_ENTRY(cef_set_crash_key_value); INIT_ENTRY(cef_set_crash_key_value);
INIT_ENTRY(cef_create_directory); INIT_ENTRY(cef_create_directory);
@ -599,14 +595,6 @@ NO_SANITIZE("cfi-icall") void cef_quit_message_loop() {
g_libcef_pointers.cef_quit_message_loop(); g_libcef_pointers.cef_quit_message_loop();
} }
NO_SANITIZE("cfi-icall") void cef_set_osmodal_loop(int osModalLoop) {
g_libcef_pointers.cef_set_osmodal_loop(osModalLoop);
}
NO_SANITIZE("cfi-icall") void cef_enable_highdpi_support() {
g_libcef_pointers.cef_enable_highdpi_support();
}
NO_SANITIZE("cfi-icall") int cef_crash_reporting_enabled() { NO_SANITIZE("cfi-icall") int cef_crash_reporting_enabled() {
return g_libcef_pointers.cef_crash_reporting_enabled(); return g_libcef_pointers.cef_crash_reporting_enabled();
} }

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory // implementations. See the translator.README.txt file in the tools directory
// for more information. // for more information.
// //
// $hash=f1ec7f73b35927e943a058141d73d449dd31e43c$ // $hash=24d0396cbcb6e2af587c1126c899277d4ac0b4d2$
// //
#include "include/capi/cef_app_capi.h" #include "include/capi/cef_app_capi.h"
@ -138,20 +138,6 @@ NO_SANITIZE("cfi-icall") CEF_GLOBAL void CefQuitMessageLoop() {
cef_quit_message_loop(); cef_quit_message_loop();
} }
NO_SANITIZE("cfi-icall") CEF_GLOBAL void CefSetOSModalLoop(bool osModalLoop) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_set_osmodal_loop(osModalLoop);
}
NO_SANITIZE("cfi-icall") CEF_GLOBAL void CefEnableHighDPISupport() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_enable_highdpi_support();
}
NO_SANITIZE("cfi-icall") CEF_GLOBAL bool CefCrashReportingEnabled() { NO_SANITIZE("cfi-icall") CEF_GLOBAL bool CefCrashReportingEnabled() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

View File

@ -1,3 +1,62 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights // Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
#include "include/base/cef_build.h"
#if defined(OS_WIN)
#include "include/base/cef_compiler_specific.h"
#include "include/base/cef_logging.h"
#include "include/cef_api_hash.h"
#include "include/internal/cef_win.h"
#if defined(ARCH_CPU_32_BITS)
NO_SANITIZE("cfi-icall")
int CefRunWinMainWithPreferredStackSize(wWinMainPtr wWinMain,
HINSTANCE hInstance,
LPWSTR lpCmdLine,
int nCmdShow) {
CHECK(wWinMain && hInstance);
const char* api_hash = cef_api_hash(0);
if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
// The libcef API hash does not match the current header API hash.
NOTREACHED();
return 0;
}
return cef_run_winmain_with_preferred_stack_size(wWinMain, hInstance,
lpCmdLine, nCmdShow);
}
int CefRunMainWithPreferredStackSize(mainPtr main, int argc, char* argv[]) {
CHECK(main);
const char* api_hash = cef_api_hash(0);
if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
// The libcef API hash does not match the current header API hash.
NOTREACHED();
return 0;
}
return cef_run_main_with_preferred_stack_size(main, argc, argv);
}
#endif // defined(ARCH_CPU_32_BITS)
NO_SANITIZE("cfi-icall") void CefEnableHighDPISupport() {
const char* api_hash = cef_api_hash(0);
if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
// The libcef API hash does not match the current header API hash.
NOTREACHED();
return;
}
cef_enable_highdpi_support();
}
NO_SANITIZE("cfi-icall") void CefSetOSModalLoop(bool osModalLoop) {
cef_set_osmodal_loop(osModalLoop);
}
#endif // defined(OS_WIN)

View File

@ -130,5 +130,22 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
int nCmdShow) { int nCmdShow) {
UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(lpCmdLine);
#if defined(ARCH_CPU_32_BITS)
// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
// stack size. This function must be called at the top of the executable entry
// point function (`main()` or `wWinMain()`). It is used in combination with
// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
// flag on executable targets. This saves significant memory on threads (like
// those in the Windows thread pool, and others) whose stack size can only be
// controlled via the linker flag.
int exit_code = CefRunWinMainWithPreferredStackSize(wWinMain, hInstance,
lpCmdLine, nCmdShow);
if (exit_code >= 0) {
// The fiber has completed so return here.
return exit_code;
}
#endif
return client::RunMain(hInstance, nCmdShow); return client::RunMain(hInstance, nCmdShow);
} }

View File

@ -28,6 +28,24 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(lpCmdLine);
int exit_code;
#if defined(ARCH_CPU_32_BITS)
// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
// stack size. This function must be called at the top of the executable entry
// point function (`main()` or `wWinMain()`). It is used in combination with
// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
// flag on executable targets. This saves significant memory on threads (like
// those in the Windows thread pool, and others) whose stack size can only be
// controlled via the linker flag.
exit_code = CefRunWinMainWithPreferredStackSize(wWinMain, hInstance,
lpCmdLine, nCmdShow);
if (exit_code >= 0) {
// The fiber has completed so return here.
return exit_code;
}
#endif
// Enable High-DPI support on Windows 7 or newer. // Enable High-DPI support on Windows 7 or newer.
CefEnableHighDPISupport(); CefEnableHighDPISupport();
@ -46,7 +64,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
// CEF applications have multiple sub-processes (render, GPU, etc) that share // CEF applications have multiple sub-processes (render, GPU, etc) that share
// the same executable. This function checks the command-line and, if this is // the same executable. This function checks the command-line and, if this is
// a sub-process, executes the appropriate logic. // a sub-process, executes the appropriate logic.
int exit_code = CefExecuteProcess(main_args, nullptr, sandbox_info); exit_code = CefExecuteProcess(main_args, nullptr, sandbox_info);
if (exit_code >= 0) { if (exit_code >= 0) {
// The sub-process has completed so return here. // The sub-process has completed so return here.
return exit_code; return exit_code;

View File

@ -108,6 +108,25 @@ int XIOErrorHandlerImpl(Display* display) {
} // namespace } // namespace
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
#if !defined(OS_MAC)
int exit_code;
#endif
#if defined(OS_WIN) && defined(ARCH_CPU_32_BITS)
// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
// stack size. This function must be called at the top of the executable entry
// point function (`main()` or `wWinMain()`). It is used in combination with
// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
// flag on executable targets. This saves significant memory on threads (like
// those in the Windows thread pool, and others) whose stack size can only be
// controlled via the linker flag.
exit_code = CefRunMainWithPreferredStackSize(main, argc, argv);
if (exit_code >= 0) {
// The fiber has completed so return here.
return exit_code;
}
#endif
#if defined(OS_MAC) #if defined(OS_MAC)
// Load the CEF framework library at runtime instead of linking directly // Load the CEF framework library at runtime instead of linking directly
// as required by the macOS sandbox implementation. // as required by the macOS sandbox implementation.
@ -153,7 +172,7 @@ int main(int argc, char* argv[]) {
} }
// Execute the secondary process, if any. // Execute the secondary process, if any.
int exit_code = CefExecuteProcess(main_args, app, windows_sandbox_info); exit_code = CefExecuteProcess(main_args, app, windows_sandbox_info);
if (exit_code >= 0) if (exit_code >= 0)
return exit_code; return exit_code;
#else #else

View File

@ -40,6 +40,7 @@ class cef_api_hash:
self.platform_files = { self.platform_files = {
# List of includes_win_capi from cef_paths2.gypi. # List of includes_win_capi from cef_paths2.gypi.
"windows": [ "windows": [
"internal/cef_app_win.h",
"internal/cef_types_win.h", "internal/cef_types_win.h",
], ],
# List of includes_mac_capi from cef_paths2.gypi. # List of includes_mac_capi from cef_paths2.gypi.