From 778943a572c20712f64e0fa4c8f4079d0d37e1f8 Mon Sep 17 00:00:00 2001 From: geekgeekrun Date: Sun, 24 Mar 2024 10:51:45 +0800 Subject: [PATCH] add suicide timer in auto chat daemon for parent and child process don't have any communication after child process spawned in 10s. --- .../ui/src/common/enums/auto-start-chat.ts | 3 +- .../index.ts | 50 ++++++++++++++++++- packages/ui/src/main/window/mainWindow.ts | 10 +++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/common/enums/auto-start-chat.ts b/packages/ui/src/common/enums/auto-start-chat.ts index 78cbfc0..5be6e34 100644 --- a/packages/ui/src/common/enums/auto-start-chat.ts +++ b/packages/ui/src/common/enums/auto-start-chat.ts @@ -4,5 +4,6 @@ export enum AUTO_CHAT_ERROR_EXIT_CODE { LOGIN_STATUS_INVALID = 82, ERR_INTERNET_DISCONNECTED = 83, ACCESS_IS_DENIED = 84, - PUPPETEER_IS_NOT_EXECUTABLE = 85 + PUPPETEER_IS_NOT_EXECUTABLE = 85, + DAEMON_PROCESS_SUICIDE = 86 } diff --git a/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/index.ts b/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/index.ts index 0a015b3..35cc3bc 100644 --- a/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/index.ts +++ b/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/index.ts @@ -2,6 +2,9 @@ import { sleep } from '@geekgeekrun/utils/sleep.mjs' import childProcess from 'node:child_process' import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../../common/enums/auto-start-chat' import { app } from 'electron' +import fs from 'node:fs' +import { pipeWriteRegardlessError } from '../utils/pipe' +import * as JSONStream from 'JSONStream' const rerunInterval = (() => { let v = Number(process.env.MAIN_BOSSGEEKGO_RERUN_INTERVAL) @@ -39,10 +42,55 @@ function runWithDaemon() { runWithDaemon() }) } + +// suicide timer for parent and child process don't have any communication after child process spawned. +let suicideTimer: NodeJS.Timeout | null = null +const setSuicideTimer = () => + (suicideTimer = setTimeout(() => { + app.exit(AUTO_CHAT_ERROR_EXIT_CODE.DAEMON_PROCESS_SUICIDE) + }, 10000)) +const clearSuicideTimer = () => { + if (suicideTimer) { + clearTimeout(suicideTimer) + } + suicideTimer = null +} + export function runAutoChatWithDaemon() { app.dock?.hide() process.on('disconnect', () => { app.exit() }) - runWithDaemon() + setSuicideTimer() + + let pipe: null | fs.WriteStream = null + try { + pipe = fs.createWriteStream(null, { fd: 3 }) + } catch { + console.error('pipe is not available') + app.exit(1) + } + + const pipeForRead: fs.ReadStream = fs.createReadStream(null, { fd: 3 }) + const pipeForReadWithJsonParser = pipeForRead.pipe(JSONStream.parse()) + pipeForReadWithJsonParser?.on('data', function waitForCanRun(data) { + if (data.type === 'GEEK_AUTO_START_CHAT_CAN_BE_RUN') { + pipeForReadWithJsonParser.off('data', waitForCanRun) + clearSuicideTimer() + runWithDaemon() + + // if don't call close, when kill child process, child process will ANR. + pipeForRead.close() + } + }) + process.on('SIGINT', () => { + process.exit() + }) + + pipeWriteRegardlessError( + pipe, + JSON.stringify({ + type: 'DAEMON_PROCESS_STARTUP' + }) + ) } diff --git a/packages/ui/src/main/window/mainWindow.ts b/packages/ui/src/main/window/mainWindow.ts index 624dc29..6850a2d 100644 --- a/packages/ui/src/main/window/mainWindow.ts +++ b/packages/ui/src/main/window/mainWindow.ts @@ -135,6 +135,14 @@ export function createMainWindow(): void { subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => { const data = raw switch (data.type) { + case 'DAEMON_PROCESS_STARTUP': { + subProcessOfPuppeteer!.stdio[3]!.write( + JSON.stringify({ + type: 'GEEK_AUTO_START_CHAT_CAN_BE_RUN' + }) + ) + break + } case 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED': { resolve(data) break @@ -228,7 +236,7 @@ export function createMainWindow(): void { ipcMain.handle('stop-geek-auto-start-chat-with-boss', async () => { mainWindow?.webContents.send('geek-auto-start-chat-with-boss-stopping') - subProcessOfPuppeteer?.kill('SIGINT') + subProcessOfPuppeteer?.kill() }) let subProcessOfBossZhipinLoginPageWithPreloadExtension: ChildProcess | null = null