fix(electron): drop the PID-file instance lock that could brick startup - #247
Merged
Conversation
📝 WalkthroughWalkthroughElectron single-instance handling now uses ChangesSingle-instance lock migration
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The app took two single-instance locks: Electron's own, and a home-made one, a directory in os.tmpdir() holding the owner's PID. A hard kill or a crash leaves that PID file behind; the staleness check then asks whether that PID is still alive, and once Windows recycles the number for an unrelated process the answer is yes, forever. The app then quits with exit code 0 before printing a single line: no window, no error dialog. Seen in the wild on 1.8.0: the lock held PID 21220, which by then belonged to another Electron app. Every launch exited in ~1.1s. app.requestSingleInstanceLock() already does this job, is released by the OS even when the process dies badly, and has no PID to confuse. The extra lock only added the failure mode, so it goes. Verified with the poisoned lock in place: the previous build quits before any startup log, this one boots (userData, global shortcut, renderer), and a second launch still quits instead of opening a duplicate.
EtienneLescot
force-pushed
the
fix/windows-single-instance-lock
branch
from
August 4, 2026 12:37
de212f2 to
5fff1b3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Symptom
Install 1.8.0 on Windows, double-click OpenScreen: nothing. No window, no error dialog, no entry in the Windows event log. The process exits with code 0 in ~1.1 s, before printing its first startup line.
Root cause
The app took two single-instance locks. Electron's own, and a home-made one in
electron/singleInstanceLock.ts: a directory inos.tmpdir()holding the owner's PID.That lock is only ever removed by its owner, on
will-quit. Kill the app, crash it, or lose it to a reboot and the PID file survives. The staleness check then asks a question that stops being meaningful the moment the OS recycles the number:isProcessRunningonly asks is some process alive with this PID, never is it us. Windows recycles PIDs freely, so sooner or later the number belongs to an unrelated program — and from then on OpenScreen is permanently unlaunchable, silently, until the user finds and deletes a directory in%TEMP%they have no reason to know exists.Observed on a 1.8.0 install: the lock held PID
21220, which by then belonged to another Electron app running on the machine.Fix
Delete the home-made lock and keep
app.requestSingleInstanceLock(), which already does the job and does it correctly:second-instance, so the "focus the existing window" behaviour is unchanged.One behaviour does change: the deleted lock keyed on
os.tmpdir()+ the user id, so it was machine-wide;requestSingleInstanceLock()keys onuserData. A dev build and the installedOpenscreenresolve differentuserDatapaths and can now run side by side. Two instances of the same build still cannot — which is the guarantee that matters for end users.The CLI carve-out (
cliCommand ? false : …, soopenscreen export/recordcan run while the GUI is open) is preserved.Net on the code: +1 / −162. A second commit syncs the four docs and the one test comment that described the deleted lock.
Verification
Built with the poisoned lock still on disk (a
pidfile naming a live, unrelated process):RECORDINGS_DIR,User Data Path,Global shortcut registeredSecond launch still quits instead of opening a duplicate, so the single-instance behaviour itself is intact.
Rebased onto
main(c1862364). Both typechecks, lint, the docs check andvitest --run electron/(31 files, 368 passed) are green locally — theCliCaptionsRunner.tsxtype errors and thewebm-seek-indexfailures seen on the previous base were fixed onmainin the meantime.For users already stuck on 1.8.0
Deleting
%TEMP%\openscreen-single-instance-<user>.lockunblocks the app immediately. After this change the file is never read again.Summary by CodeRabbit
Refactor
Documentation