Description
Preflight Checklist
- I have read the Contributing Guidelines for this project.
- I agree to follow the Code of Conduct that this project adheres to.
- I have searched the issue tracker for a bug report that matches the one I want to file, without success.
Electron Version
18 (any version, through at least 18.2.1)
What operating system are you using?
Windows
Operating System Version
Windows 10 21H1
What arch are you using?
x64
Last Known Working Electron version
17.4.1
Expected Behavior
App shouldn't crash when run in multiple Windows user sessions (running the app as two separate Windows users) with app.requestSingleInstanceLock
. Each separate Windows user session should support its own separate "single" app instance.
Actual Behavior
The second instance in a separate user session calls CreateNamedPipe
at https://github.com/electron/electron/pull/31460/files#diff-aeb3ae283fcbd712d19bf743d031b51f2b2fcd9e6122e5d5303a12acfdeeb447R506 and sees INVALID_HANDLE_VALUE
with ERROR_ACCESS_DENIED
, and crashes on the subsequent CHECK
.
Testcase Gist URL
No response
Additional Information
Here is a simple app that enforces a single instance per Windows user session and demonstrates the issue:
const {app} = require('electron');
if (!app.requestSingleInstanceLock()) {
console.log('second instance exiting');
app.quit();
} else {
console.log('first instance running');
}
In Electron 17.4.1, you can run it in separate Windows user sessions and they'll both print "first instance running". In Electron 18 (any version), the second one will crash.
The problem is that named pipes are not session-specific like the window and mutex objects created in process_singleton_win.cc
that are used to synchronize/communicate between processes.
Even if the named pipe were session-specific, there is still a race condition where if multiple "second instances" of different Electron apps (or of the same app) run at the same time, they could get acks meant for other ones. Rather than have a single named pipe name that's shared across all apps and instances, would it make sense to have the second instance pass the first instance a duplicated handle to either 1) an anonymous pipe or 2) shared memory + a mutex or event? I think this would be safer than the suggestion in #33777 (comment) of having the second instance have its own message window (presumably that would have to be found using the same user data directory string window lookup mechanism, and that would still have problems with multiple second instances running simultaneously that share the same user data directory).