Skip to content

Force process exit when the main window closes (#12172)#12198

Merged
niksedk merged 1 commit into
mainfrom
fix/force-exit-on-close-12172
Jul 5, 2026
Merged

Force process exit when the main window closes (#12172)#12198
niksedk merged 1 commit into
mainfrom
fix/force-exit-on-close-12172

Conversation

@niksedk

@niksedk niksedk commented Jul 5, 2026

Copy link
Copy Markdown
Member

Addresses #12172

Problem

A user reported that after closing SubtitleEdit, a SubtitleEdit.exe process kept running as a background process (~113 MB, invisible — not in the taskbar), and this locked the folder it had been working in (needed a third-party unlocker to release it).

Root cause

The app runs with ShutdownMode.OnLastWindowClose (Program.cs), so the process only exits when the last Avalonia Window closes. Any single stray window keeps it alive:

  • a leaked non-taskbar PleaseWaitWindow (ShowInTaskbar = false) whose Close() was skipped on some path, or
  • an undocked video/audio window (they actively cancel their own close unless AllowClose is set, and are only closed by MainViewModel.CleanUp()).

While the process lingers it still holds OS handles — an open video file handle, or the process current directory (libmpv temporarily sets it) — and on Windows that locks the folder. Nothing inside the app releases those; only process exit does. So the folder lock is a symptom of the process never terminating.

Fix

Hook the main window's Closed event and force Environment.Exit(0).

Why this is the right trigger:

  • It must be the main window closing, not lifetime.Start() returning — a leaked window prevents OnLastWindowClose from ever firing, so Start() would never return.
  • By the time Closed fires, the main window's OnClosing has already saved settings and run CleanUp() (which closes the undocked windows).
  • Closed never fires on a cancelled close (unsaved-changes prompt sets e.Cancel = true), so we never exit prematurely.

This guarantees shutdown regardless of any stray window, native thread, or child handle still lingering. Applies to both the normal main window and the standalone Batch Convert window (both set lifetime.MainWindow).

Notes

The exact leak that stranded the window in the original report couldn't be reproduced from the bug (no repro steps, filed against the older v5.0.0.0). This is a defensive backstop for the whole class of "lingering background process" bugs rather than a fix for one specific leak. Builds clean (0 warnings / 0 errors).

🤖 Generated with Claude Code

With ShutdownMode.OnLastWindowClose a single stray window keeps the app
alive as an invisible background process - e.g. a leaked non-taskbar
"please wait" progress window or an undocked video/audio window. Such a
lingering process holds file/current-directory handles and locks the
folder it was working in, so the user can't delete or move it.

Hook the main window's Closed event and Environment.Exit(0) there. By the
time Closed fires the main window's OnClosing has already saved settings
and run CleanUp(); Closed never fires on a cancelled (unsaved-changes)
close, so this is safe and guarantees shutdown regardless of any window,
native thread, or child handle still lingering.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@niksedk niksedk merged commit ce69663 into main Jul 5, 2026
1 of 3 checks passed
@niksedk niksedk deleted the fix/force-exit-on-close-12172 branch July 5, 2026 06:19
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.

1 participant