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 0be81ae07c85095ac2c920436b97557c95c1c524. * 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:
parent
b24cfe17bc
commit
e3fe80e0e8
2 changed files with 81 additions and 5 deletions
|
@ -103,7 +103,75 @@ namespace crash_reporter {
|
||||||
extern const char kCrashpadProcess[];
|
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) {
|
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 {
|
struct Arguments {
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||||
|
@ -198,6 +266,11 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||||
return crashpad_status;
|
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))
|
if (!electron::CheckCommandLineArguments(arguments.argc, arguments.argv))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const { app, BrowserWindow } = require('electron');
|
const { app, BrowserWindow } = require('electron');
|
||||||
|
|
||||||
app.once('ready', () => {
|
app.once('ready', async () => {
|
||||||
const w = new BrowserWindow({
|
const w = new BrowserWindow({
|
||||||
show: false,
|
show: false,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
|
@ -8,9 +8,12 @@ app.once('ready', () => {
|
||||||
nodeIntegration: true
|
nodeIntegration: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
w.webContents.once('crashed', () => {
|
w.webContents.once('render-process-gone', (_, details) => {
|
||||||
app.quit();
|
if (details.reason === 'crashed') {
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
process.exit(details.exitCode);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
w.webContents.loadURL('about:blank');
|
await w.webContents.loadURL('chrome://checkcrash');
|
||||||
w.webContents.executeJavaScript('process.crash()');
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue