Suppress recoverable Chromium child crash reports (#2762)
This commit is contained in:
parent
b24cc8087a
commit
4a8253a99e
|
|
@ -105,6 +105,113 @@ describe('shouldRecordProcessGoneCrash', () => {
|
|||
).toBe(false)
|
||||
})
|
||||
|
||||
it('skips Windows control termination killed events outside expected lifecycle teardown', () => {
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'renderer',
|
||||
reason: 'killed',
|
||||
exitCode: -1073741510,
|
||||
expectedTeardown: 'none'
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'child',
|
||||
reason: 'killed',
|
||||
exitCode: 1073807364,
|
||||
expectedTeardown: 'none'
|
||||
})
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it('skips recoverable Chromium child process exits', () => {
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'child',
|
||||
processType: 'GPU',
|
||||
reason: 'crashed',
|
||||
exitCode: -2147483645,
|
||||
expectedTeardown: 'none'
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'child',
|
||||
processType: 'gpu',
|
||||
reason: 'killed',
|
||||
exitCode: 1,
|
||||
expectedTeardown: 'none'
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'child',
|
||||
processType: 'Utility',
|
||||
serviceName: 'network.mojom.NetworkService',
|
||||
reason: 'killed',
|
||||
exitCode: 9,
|
||||
expectedTeardown: 'none'
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'child',
|
||||
processType: 'Utility',
|
||||
serviceName: 'network.mojom.NetworkService',
|
||||
reason: 'crashed',
|
||||
exitCode: -1,
|
||||
expectedTeardown: 'none'
|
||||
})
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it('still records unknown child process crashes', () => {
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'child',
|
||||
processType: 'Utility',
|
||||
serviceName: 'com.orca.unexpected',
|
||||
reason: 'crashed',
|
||||
exitCode: 5,
|
||||
expectedTeardown: 'none'
|
||||
})
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('still records severe Chromium child process failures', () => {
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'child',
|
||||
processType: 'GPU',
|
||||
reason: 'oom',
|
||||
exitCode: 1,
|
||||
expectedTeardown: 'none'
|
||||
})
|
||||
).toBe(true)
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'child',
|
||||
processType: 'Utility',
|
||||
serviceName: 'network.mojom.NetworkService',
|
||||
reason: 'launch-failed',
|
||||
exitCode: -1,
|
||||
expectedTeardown: 'none'
|
||||
})
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('still records renderer kills from the recent Linux crash-report cluster', () => {
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'renderer',
|
||||
processType: 'renderer',
|
||||
reason: 'killed',
|
||||
exitCode: 61696,
|
||||
expectedTeardown: 'none'
|
||||
})
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('records non-SIGTERM killed process exits outside expected lifecycle teardown', () => {
|
||||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
|
|
@ -121,7 +228,8 @@ describe('shouldRecordProcessGoneCrash', () => {
|
|||
expect(
|
||||
shouldRecordProcessGoneCrash({
|
||||
source: 'child',
|
||||
processType: 'GPU',
|
||||
processType: 'Utility',
|
||||
serviceName: 'com.orca.unexpected',
|
||||
reason: 'killed',
|
||||
exitCode: 9,
|
||||
expectedTeardown: 'renderer-reload'
|
||||
|
|
|
|||
|
|
@ -1,26 +1,64 @@
|
|||
export type ProcessGoneSource = 'renderer' | 'child'
|
||||
export type ExpectedTeardownScope = 'none' | 'renderer-reload' | 'app-shutdown'
|
||||
|
||||
const WINDOWS_CONTROL_TERMINATION_EXIT_CODES = new Set([0xc000013a, 0x40010004])
|
||||
const RECOVERABLE_CHILD_PROCESS_TYPES = new Set(['gpu'])
|
||||
const RECOVERABLE_UTILITY_SERVICE_NAMES = new Set(['network.mojom.NetworkService'])
|
||||
const RECOVERABLE_CHILD_PROCESS_REASONS = new Set(['crashed', 'killed'])
|
||||
|
||||
function isWindowsControlTerminationExitCode(exitCode: number | null): boolean {
|
||||
if (exitCode === null) {
|
||||
return false
|
||||
}
|
||||
return WINDOWS_CONTROL_TERMINATION_EXIT_CODES.has(exitCode >>> 0)
|
||||
}
|
||||
|
||||
function isRecoverableChromiumChildProcess({
|
||||
source,
|
||||
processType,
|
||||
serviceName,
|
||||
reason
|
||||
}: {
|
||||
source: ProcessGoneSource
|
||||
processType?: string
|
||||
serviceName?: string
|
||||
reason: string
|
||||
}): boolean {
|
||||
if (source !== 'child') {
|
||||
return false
|
||||
}
|
||||
if (!RECOVERABLE_CHILD_PROCESS_REASONS.has(reason)) {
|
||||
return false
|
||||
}
|
||||
const normalizedProcessType = processType?.toLowerCase()
|
||||
if (normalizedProcessType && RECOVERABLE_CHILD_PROCESS_TYPES.has(normalizedProcessType)) {
|
||||
return true
|
||||
}
|
||||
return (
|
||||
normalizedProcessType === 'utility' &&
|
||||
serviceName !== undefined &&
|
||||
RECOVERABLE_UTILITY_SERVICE_NAMES.has(serviceName)
|
||||
)
|
||||
}
|
||||
|
||||
export function shouldRecordProcessGoneCrash({
|
||||
source,
|
||||
processType,
|
||||
serviceName,
|
||||
reason,
|
||||
exitCode,
|
||||
expectedTeardown
|
||||
}: {
|
||||
source: ProcessGoneSource
|
||||
processType: string
|
||||
processType?: string
|
||||
serviceName?: string
|
||||
reason: string
|
||||
exitCode: number | null
|
||||
expectedTeardown: ExpectedTeardownScope
|
||||
}): boolean {
|
||||
// Why: Chromium's GPU helper can emit a crash-shaped exit while Electron is
|
||||
// already intentionally exiting/relaunching; that is shutdown noise.
|
||||
if (
|
||||
expectedTeardown === 'app-shutdown' &&
|
||||
source === 'child' &&
|
||||
processType.toLowerCase() === 'gpu'
|
||||
) {
|
||||
// Why: GPU and Network Service exits are recoverable Chromium child-process
|
||||
// churn; treating them as app crashes creates noisy user prompts.
|
||||
if (isRecoverableChromiumChildProcess({ source, processType, serviceName, reason })) {
|
||||
return false
|
||||
}
|
||||
// Why: Electron reports intentional reload/update/quit teardown as `killed`.
|
||||
|
|
@ -29,8 +67,9 @@ export function shouldRecordProcessGoneCrash({
|
|||
return true
|
||||
}
|
||||
// Why: Electron reports expected Chromium teardown during reload/update as
|
||||
// `killed` + SIGTERM. Treat real crash reasons as reportable, but skip this.
|
||||
if (exitCode === 15) {
|
||||
// `killed` + SIGTERM or Windows control termination statuses. Treat real
|
||||
// crash reasons as reportable, but skip these normal termination shapes.
|
||||
if (exitCode === 15 || isWindowsControlTerminationExitCode(exitCode)) {
|
||||
return false
|
||||
}
|
||||
if (expectedTeardown === 'app-shutdown') {
|
||||
|
|
|
|||
|
|
@ -531,6 +531,7 @@ function recordProcessGoneCrash(
|
|||
!shouldRecordProcessGoneCrash({
|
||||
source,
|
||||
processType,
|
||||
serviceName: typeof details.serviceName === 'string' ? details.serviceName : undefined,
|
||||
reason,
|
||||
exitCode,
|
||||
expectedTeardown: getExpectedTeardownScope(webContentsId)
|
||||
|
|
|
|||
Loading…
Reference in New Issue