fix: resolve Windows gateway reconnect race condition and translate comments (#787)

This commit is contained in:
paisley
2026-04-07 16:58:18 +08:00
committed by GitHub
Unverified
parent d8750e135b
commit c3a735a49c
5 changed files with 97 additions and 17 deletions

View File

@@ -775,8 +775,19 @@ export class GatewayManager extends EventEmitter {
if (this.status.state === 'running') {
this.setStatus({ state: 'stopped' });
this.scheduleReconnect();
}
// Always attempt reconnect from process exit. scheduleReconnect()
// internally checks shouldReconnect and reconnect-timer guards, so
// calling it unconditionally is safe — intentional stop() calls set
// shouldReconnect=false which makes scheduleReconnect() no-op.
//
// On Windows, the WS close handler intentionally skips reconnect
// (to avoid racing with this exit handler). However, WS close
// fires *before* process exit and sets state='stopped', which
// previously caused this handler to also skip reconnect — leaving
// the gateway permanently dead with no recovery path.
this.scheduleReconnect();
},
onError: () => {
this.ownsProcess = false;

View File

@@ -162,7 +162,12 @@ export async function launchGatewayProcess(options: {
});
child.on('exit', (code: number) => {
const expectedExit = !options.getShouldReconnect() || options.getCurrentState() === 'stopped';
// Only check shouldReconnect — not current state. On Windows the WS
// close handler fires before the process exit handler and sets state to
// 'stopped', which would make an unexpected crash look like a planned
// shutdown in logs. shouldReconnect is the reliable indicator: stop()
// sets it to false (expected), crashes leave it true (unexpected).
const expectedExit = !options.getShouldReconnect();
const level = expectedExit ? logger.info : logger.warn;
level(`Gateway process exited (code=${code}, expected=${expectedExit ? 'yes' : 'no'})`);
options.onExit(child, code);