fix: increase stack size on windows x86 (#29474)

* fix: increace main thread stack size on windows x86

* chore: improve quit-on-crashed-event spec

* chore: add debug logs

* Revert "chore: add debug logs"

This reverts commit 0be81ae07c.

* chore: use a reliable crash endpoint

Co-authored-by: Stephen Wang <wangwenqiang.wwq@bytedance.com>
Co-authored-by: Deepak Mohan <hop2deep@gmail.com>
This commit is contained in:
stephen9357 2021-07-23 03:49:21 +08:00 коммит произвёл GitHub
Родитель b24cfe17bc
Коммит e3fe80e0e8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 81 добавлений и 5 удалений

Просмотреть файл

@ -103,7 +103,75 @@ namespace crash_reporter {
extern const char kCrashpadProcess[];
}
// 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 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 {
HINSTANCE instance;
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 wWinMain 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.
fiber_state->fiber_result =
wWinMain(fiber_state->instance, nullptr, nullptr, 0);
// Switch back to the main thread to exit.
::SwitchToFiber(fiber_state->original_fiber);
}
#endif // defined(ARCH_CPU_32_BITS)
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
#if defined(ARCH_CPU_32_BITS)
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) {
FiberState fiber_state = {instance, 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 Chrome 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.
#endif // defined(ARCH_CPU_32_BITS)
struct Arguments {
int argc = 0;
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
@ -198,6 +266,11 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
return crashpad_status;
}
#if defined(ARCH_CPU_32_BITS)
// Intentionally crash if converting to a fiber failed.
CHECK_EQ(fiber_status, FiberStatus::kSuccess);
#endif // defined(ARCH_CPU_32_BITS)
if (!electron::CheckCommandLineArguments(arguments.argc, arguments.argv))
return -1;

Просмотреть файл

@ -1,6 +1,6 @@
const { app, BrowserWindow } = require('electron');
app.once('ready', () => {
app.once('ready', async () => {
const w = new BrowserWindow({
show: false,
webPreferences: {
@ -8,9 +8,12 @@ app.once('ready', () => {
nodeIntegration: true
}
});
w.webContents.once('crashed', () => {
app.quit();
w.webContents.once('render-process-gone', (_, details) => {
if (details.reason === 'crashed') {
process.exit(0);
} else {
process.exit(details.exitCode);
}
});
w.webContents.loadURL('about:blank');
w.webContents.executeJavaScript('process.crash()');
await w.webContents.loadURL('chrome://checkcrash');
});