fix(stage-tamagotchi): make handleAppExit more robust (#1321)

* fix(stage-tamagotchi): make handleAppExit more robust

* chore: code style update

* chore: code style update

---------

Co-authored-by: Garfield Lee <Garfield550@users.noreply.github.com>
This commit is contained in:
Makito
2026-03-12 23:55:26 +08:00
committed by GitHub
co-authored by Garfield Lee
parent c897aade2e
commit 4c7bd5522b
+32 -7
View File
@@ -83,6 +83,7 @@ electronApp.setAppUserModelId('ai.moeru.airi')
initScreenCaptureForMain()
let fileLogger: FileLoggerHandle = nullFileLoggerHandle
let skipFileLogging = false
app.whenReady().then(async () => {
// Initialize file logger and register the hook
@@ -90,9 +91,9 @@ app.whenReady().then(async () => {
// Register the global hook for file logging
setGlobalHookPostLog((_, formatted) => {
if (fileLogger.logFileFd !== null) {
void fileLogger.appendLog(formatted)
}
if (skipFileLogging || fileLogger.logFileFd === null)
return
void fileLogger.appendLog(formatted)
})
injeca.setLogger(createLoggLogger(useLogg('injeca').useGlobalConfig()))
@@ -211,13 +212,37 @@ async function handleAppExit() {
appExiting = true
let exitedNormally = true
/**
* Safely execute fn and log any errors that occur, marking the exit as abnormal
* if an error is caught.
*
* @param operation - A verb phrase describing the operation.
* @param fn - Any function to execute. It can be either sync or async.
* @returns A promise that resolves when the operation is complete.
*/
async function logIfError(operation: string, fn: () => unknown): Promise<void> {
try {
await fn()
}
catch (error) {
exitedNormally = false
log.withError(error).error(`[app-exit] Failed to ${operation}:`)
}
}
await Promise.all([
emitAppBeforeQuit(),
injeca.stop(),
fileLogger.close(), // Ensure all logs are flushed
logIfError('execute onAppBeforeQuit hooks', () => emitAppBeforeQuit()),
logIfError('stop injeca', () => injeca.stop()),
])
app.exit(0)
// Prevent the global log hook from trying to write to the file after close() is called,
// which would cause a recursive failure if close() itself throws.
skipFileLogging = true
await logIfError('flush file logs', () => fileLogger.close()) // Ensure all logs are flushed
app.exit(exitedNormally ? 0 : 1)
}
process.on('SIGINT', () => handleAppExit())