mirror of
https://github.com/larksuite/cli.git
synced 2026-07-03 14:02:43 +08:00
* fix(mail): replace os.Exit with graceful shutdown in mail watch The signal handler in mail +watch called os.Exit(0), which bypassed all deferred cleanup functions, made the code path untestable, and did not follow Go's idiomatic context cancellation pattern. Key changes: - Remove os.Exit(0) and use context.WithCancel to propagate shutdown - Run cli.Start in a separate goroutine so the main goroutine can return immediately on signal receipt (the Lark WebSocket SDK does not return promptly after context cancellation) - Extract handleMailWatchSignal as a testable standalone function - Use sync.Once + defer for idempotent cleanup on all exit paths - Fix eventCount data race with atomic.Int64 - Add signal.Reset to support forced termination via a second Ctrl+C Closes #268 * docs: add docstrings to handleMailWatchSignal test functions * fix(mail): cancel watch context on signal handler panic If handleMailWatchSignal panics, the recover block now calls cancelWatch() to unblock the main select. Without this, a panic would leave shutdownBySignal unclosed and watchCtx uncancelled, causing the process to hang. * fix(mail): use triggerShutdown to unblock main select on signal handler panic The previous panic recovery only called cancelWatch(), but since the WebSocket SDK does not return promptly after context cancellation, the main select could still hang waiting on startErrCh. Introduce triggerShutdown() that closes shutdownBySignal (via sync.Once) and cancels the watch context, used by both the normal signal path and the panic recovery path. This ensures the main select unblocks immediately regardless of how the signal goroutine exits. Add regression test that forces a panic and asserts shutdownBySignal is closed promptly.