зеркало из https://github.com/electron/electron.git
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:
Родитель
b24cfe17bc
Коммит
e3fe80e0e8
|
@ -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');
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче