Skip to content

Comments

fix: properly cleanup Windows process tree on Obsidian exit#24

Closed
Gerkinfeltser wants to merge 2 commits intomtymek:mainfrom
Gerkinfeltser:fix/windows-process-cleanup
Closed

fix: properly cleanup Windows process tree on Obsidian exit#24
Gerkinfeltser wants to merge 2 commits intomtymek:mainfrom
Gerkinfeltser:fix/windows-process-cleanup

Conversation

@Gerkinfeltser
Copy link
Contributor

Problem

On Windows, when Obsidian is closed with the OpenCode panel open, the server process (node.exe) is not terminated and becomes an orphaned process. This happens because:

  1. The server is spawned with shell: true, which creates cmd.exe → node.exe
  2. The PID captured is cmd.exe, not the actual node.exe
  3. When Obsidian exits, onunload() tries to kill the PID, but cmd.exe dies leaving node.exe orphaned
  4. The child process lookup using WMIC was failing silently

Solution

Store the PID separately in main.ts and use PowerShell to reliably find and kill child processes:

  1. Store PID separately: Added serverPid field to track the process PID independently of ProcessManager (which gets destroyed before onunload() fires)
  2. PowerShell child lookup: Replaced WMIC with PowerShell's Get-CimInstance which is more reliable on modern Windows
  3. beforeunload handler: Added cleanup handler for window close event (more reliable than onunload on Windows)
  4. Triple-kill strategy:
    • Kill child processes (actual node.exe) using PowerShell
    • Kill parent process (cmd.exe)
    • Fallback: kill by command line pattern using WMIC (port-based)

Testing

Tested on Windows 11:

  • Server starts correctly
  • Server stops when clicking panel close button
  • Server stops when closing Obsidian window
  • No orphaned node.exe processes after exit

Breaking Changes

None. The fix maintains backward compatibility.

Spawned shell process (cmd.exe) was being killed but orphaned the actual
node.exe child. Fix uses PowerShell to find and kill child processes first,
using the stored PID from before Obsidian destroys the ProcessManager.

Changes:
- Store server PID in main.ts separately
- Add killPidSync() with PowerShell child lookup (Windows)
- Add beforeunload handler for cleanup during window close
- Add getPid() method to ProcessManager
- Remove unused quit event handler

Also added esModuleInterop to tsconfig.json and tree-kill dependency
(though not used in final solution).
The test was checking for not found error message, but the actual
error is Process exited unexpectedly exit code 1. Updated the
assertion to check for exit code pattern which covers both cases.
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