Skip to content

fix: End sessions on Windows shutdown and app.exit() - #1486

Open
timfish wants to merge 3 commits into
masterfrom
ccr-80b9cd2e-dyyfmx
Open

timfish wants to merge 3 commits into
masterfrom
ccr-80b9cd2e-dyyfmx

Conversation

@timfish

@timfish timfish commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #1477

On Windows, before-quit and will-quit are not emitted on system shutdown, restart or user logoff. app.exit() skips both events on all platforms. In these cases the main process session stayed ok on disk, and the next start reported it as abnormal. Long-running tray apps got an abnormal session after every reboot.

Changes

  • On Windows, listen for the session-end event on every BrowserWindow. When it fires, write the session to disk as exited.
  • Wrap app.exit() so that it writes the session to disk as exited before the app exits.
  • The write is synchronous (new Store.setSync()), because Windows can end the process soon after session-end and async work may not finish.
  • The session is not ended in memory. If the app still exits through will-quit, the normal path sends the session and clears the file, so it is not sent twice.
  • On the next start, a persisted exited session is sent with its original end time and duration. If a minidump from the previous run is found, the session is still reported as crashed.
  • previousSessionWasAbnormal() now calls checkPreviousSession(false) instead of duplicating its code.

Behaviour change: process.exit()

From Electron 43, process.exit() in the main process calls app.exit(). Because of this, a session that ends with process.exit() is now reported as exited on Electron 43 and later. On older Electron versions it is still reported as abnormal.

The abnormal-exit and abnormal-exit-electron-uploader e2e tests used process.exit() to simulate an abnormal exit, so they now kill the app with SIGKILL. This gives a real abnormal exit on all Electron versions.

Limitations

  • Windows apps with no open window still get abnormal after a shutdown, because session-end is a BrowserWindow event and Electron has no app-level equivalent on Windows.
  • The session-end path is not covered by an automated test, because it needs a real Windows logoff or shutdown.

Tests

  • New e2e test sessions/app-exit: the first run exits with app.exit(), and the second run must send that session as exited. It fails on master with abnormal.

Generated by Claude Code

On Windows, 'before-quit' and 'will-quit' are not emitted on system shutdown, restart or user logoff. app.exit() skips both events on all platforms. In these cases the session stayed 'ok' on disk and the next start reported it as 'abnormal'.

Now the session is written to disk as 'exited' on the BrowserWindow 'session-end' event (Windows) and when app.exit() is called. The write is synchronous because the process can end before async work finishes. On the next start, a persisted 'exited' session is sent as is, unless a crash is found.
From Electron 43, process.exit() calls app.exit(). The SDK now treats app.exit() as a clean exit, so these tests got an 'exited' session. SIGKILL gives a real abnormal exit on all Electron versions.
@timfish
timfish marked this pull request as ready for review November 3, 2026 11:39

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6d9acee. Configure here.

Comment thread src/main/store.ts Resolved
An async set() that started before setSync() could finish after it and write the old 'ok' session back to disk. Async writes queued before a sync write are now skipped. If a sync write happens while an async write runs, the sync data is written again.
@timfish
timfish requested a review from JPeer264 November 3, 2026 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sessions not ended on Windows shutdown/logoff or app.exit()

1 participant