Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Use async randomBytes API to speedup Windows startup #19242

Merged
merged 2 commits into from May 1, 2019

Conversation

rafeca
Copy link
Contributor

@rafeca rafeca commented Apr 30, 2019

This PR changes a bit the logic of atom-application to make the authentication through sockets async, which fixes #19239.

In order to make the code async and keep it as robust as possible a few changes needed to be done (basically to delay the execution of some logic while avoiding as much as possible potential race conditions).

This way we avoid delaying the opening of a project when reusing an
existing Atom window.
Copy link
Contributor

@smashwilson smashwilson left a comment

Choose a reason for hiding this comment

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

👍 LGTM

@@ -15,6 +15,7 @@ const path = require('path')
const os = require('os')
const net = require('net')
const url = require('url')
const {promisify} = require('util')
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh hey! I didn't realize we had access to promisify now. This will come in handy.

@@ -227,11 +230,16 @@ class AtomApplication extends EventEmitter {
this.applicationMenu = new ApplicationMenu(this.version, this.autoUpdateManager)
this.atomProtocolHandler = new AtomProtocolHandler(this.resourcePath, this.safeMode)

this.listenForArgumentsFromNewProcess()
// Don't await for the following method to avoid delaying the opening of a new window.
// (we await it just after opening it).
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Excellent.

Copy link
Contributor

Choose a reason for hiding this comment

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

Again, worth mentioning explicitly that this method is slow on Windows?

listenForArgumentsFromNewProcess () {
if (!this.socketPath) return
async listenForArgumentsFromNewProcess (options) {
if (!options.test && !options.benchmark && !options.benchmarkTest) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I still wish we had a more succinct way to express "a regular editor window" in these options. (Out of scope for this PR though.)

@rafeca rafeca merged commit 0132e1e into master May 1, 2019
@rafeca rafeca deleted the use-async-randombytes branch May 1, 2019 13:43
Copy link
Contributor

@nathansobo nathansobo left a comment

Choose a reason for hiding this comment

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

I think it might be helpful to clarify the motivations behind not awaiting in comments. So just checking my understanding... this increases the window of time in which a race condition might exist, correct? I suppose there was always a small window anyway if you ran atom twice quickly before the first Electron could start listening on the socket. This just makes it more likely.

Another question: Is there some way we can remember to revisit this when we upgrade Electron and see if crypto is still so slow?


return socketSecret
}

const encryptOptions = (options, secret) => {
const message = JSON.stringify(options)

const initVector = crypto.randomBytes(16)
// Even if the following IV is not cryptographically secure, there's a really good chance
// it's going to be unique between executions which is the requirement for GCM.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it might be helpful to future readers if you explain the motivation for avoiding cryptographic randomness on this code path (that it's too slow).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added more explicit comments for both things in #19246

@@ -227,11 +230,16 @@ class AtomApplication extends EventEmitter {
this.applicationMenu = new ApplicationMenu(this.version, this.autoUpdateManager)
this.atomProtocolHandler = new AtomProtocolHandler(this.resourcePath, this.safeMode)

this.listenForArgumentsFromNewProcess()
// Don't await for the following method to avoid delaying the opening of a new window.
// (we await it just after opening it).
Copy link
Contributor

Choose a reason for hiding this comment

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

Again, worth mentioning explicitly that this method is slow on Windows?

@rafeca
Copy link
Contributor Author

rafeca commented May 1, 2019

I think it might be helpful to clarify the motivations behind not awaiting in comments. So just checking my understanding... this increases the window of time in which a race condition might exist, correct? I suppose there was always a small window anyway if you ran atom twice quickly before the first Electron could start listening on the socket. This just makes it more likely.

Exactly, it'll make this window (which is already a few hundred ms) unnoticeable longer in OSX/Linux (a few ticks) and quite much longer (up to a second) in Windows (at least until we upgrade to electron v3).

I think that's a fair tradeoff, since the only side effect that this will cause is that two Atom windows will get opened under that situation.

Another question: Is there some way we can remember to revisit this when we upgrade Electron and see if crypto is still so slow?

Maybe we can use a specially-crafted comment that's easy to search on GitHub for the whole Atom org, and then we add a point to the electron upgrade manual doc (if it exists) to revisit all these messages whenever we upgrade the electron version?

Something like:

// TodoElectronIssue: `randomBytes` is slow on electron v2. This issue is fixed in v3.

(I'm not using spaces/special characters since GitHub search is particularly bad when searching for non-words).

@50Wliu
Copy link
Contributor

50Wliu commented May 1, 2019

Another question: Is there some way we can remember to revisit this when we upgrade Electron and see if crypto is still so slow?

In addition to what @rafeca suggested, we could also create a tracking issue for it and apply the electron label, as our Electron upgrade checklist specifies to check each one and see if they have been fixed/can be resolved with the new Electron version.

rafeca added a commit that referenced this pull request May 7, 2019
Use async randomBytes API to speedup Windows startup
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Performance regression in v1.36.1
4 participants