-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"Fix" repl race condition #1677
Conversation
throw err; | ||
console.log('Encountered error with persistent history support.'); | ||
return cliRepl.createInternalRepl( | ||
process.env, false, function(err, repl) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like an odd style choice, but make jslint
didn't complain!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The linter is set up pretty conservative right now. Not sure it has a rule for odd linebreaks, but it seems fine to me there.
if (!tmpPath) { | ||
return ready(new Error('no tmpdir available')); | ||
} | ||
tmpPath = path.join(tmpPath, process.pid + '-' + 'repl.tmp'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe 'node-repl-' + process.pid
to make it clear which process created that file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
Recently had the issue that the REPL failed to spawn because some error when reading the history file, so I'd appreciate this being landed. The linter changes should go, they're not needed anymore. |
Another thing that would make the REPL history much more reliable is if it didn't save json, only lines of text. A few lines of garbled history is much better than the REPL refusing to open because of history corruption. |
Totally agree, lines should be stored as lines. |
useGlobal: true | ||
}; | ||
|
||
if (parseInt(env.NODE_NO_READLINE)) { | ||
opts.terminal = false; | ||
} | ||
if (parseInt(env.NODE_FORCE_READLINE)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we use the radix here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't be a problem in this case – we're just detecting whether the number is "0" or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then we can explicitly do that right? As it is, the intention of this code is not clear, IMO.
|
Edit: i think this will get too messy, see below. |
Or, you know, just drop JSON support in a major, with an automatic conversion to line-based history in place. People who are using persistent history are early adopters that read changelogs, and I don't think many users will downgrade to previous versions of iojs. nvm is mostly used to switch between 0.10, 0.12 and iojs. If they really hit a iojs version that doesn't support line-based history, they'll know what to do. Let's do it right, while the feature is still young, imho. |
Here's one reason you might want to keep storing lines as JSON: users can enter multi-line input in the REPL (e.g. type a |
@bnoordhuis Could I get an LGTM on this (or a "this approach will not work?") |
I don't think this PR is still applicable - https://github.com/chrisdickinson/io.js/commit/46e2d6848ef33461757a4c43939c8b3adbf10784 was replaced by #1686, and the race conditions were fixed in d200932...ed6c249. I'll close this for now, it can be reopened if I'm mistaken. |
I didn't actually fix the race conditions. Doing that requires considerably more work. I did make them have minimal impact though. |
@chrisdickinson @Fishrock123 ... any progress on this? |
@jasnell After some changes that I did it's much less prone to catastrophic error, but it still could work properly. It's pretty complex though. (It's unlikely that I understand enough about atomic file operations to do this properly.) |
@chrisdickinson ... ping :-) |
I haven't really seen any complaints about history race conditions since (it might have faded into "general weirdness that folks expect out of history-backed REPLs".) Closing this. |
For some value of "fix."
Per #1634, having multiple CLI repls open could lead to inconsistencies in the JSON data being stored. This PR changes the internal repl so that it commits to a temporary file first, then renames it to the target file. @bnoordhuis noted that this will only work if the tmpdir and target dir are on the same mount, but I imagine the worst case is not any worse than conflicting, racing writes, and this should solve the 80% use case.
This PR also re-addresses the problem of non-terminal readline instances corrupting history. Now the internal repl always defaults the written history to
[]
(vs. trying to set the options in internal/repl as before.)Additionally, the PR makes it so that repls that fail to load history (for whatever reason) don't crash out – they simply continue without persistent history support.
Finally, this adds the internal modules to the list of files checked by eslint.
Will fix up the commit log once review is over, as I suspect reviewers will have thoughts about the strategy I've taken here!
R=@indutny, @bnoordhuis