repl: fix freeze if util.inspect throws & clean up error handling a bit#1968
repl: fix freeze if util.inspect throws & clean up error handling a bit#1968monsanto wants to merge 2 commits intonodejs:masterfrom monsanto:fix-freeze
Conversation
If an error is thrown during the readline `keypress` event, the state of the streaming escape sequence decoder (added in #1601) will become corrupted. This will render the REPL (and possibly your whole terminal) completely unusable. This can be triggered by an object with a custom `inspect` method that throws. This commit adds an extra try/catch around `self.writer` (which is `util.inspect` by default).
lib/repl.js
Outdated
There was a problem hiding this comment.
This logic is moved to finish so all of the error handling can be in one place. It doesn't seem safe to do this here anyway since the evaluation function can be overriden. The explicit process.domain.exit is not carried over as 1) I don't understand what use it serves & I don't like to blindly c/p, 2) the other existing domain emit didn't come with an exit and 3) the repl+domain test passes without it. @isaacs you added this 2 years ago, do you remember?
|
diff --git a/lib/readline.js b/lib/readline.js
index 4107c99..b8f52ee 100644
--- a/lib/readline.js
+++ b/lib/readline.js
@@ -910,7 +910,15 @@ function emitKeypressEvents(stream) {
var r = stream[KEYPRESS_DECODER].write(b);
if (r) {
for (var i = 0; i < r.length; i++) {
- stream[ESCAPE_DECODER].next(r[i]);
+ try {
+ stream[ESCAPE_DECODER].next(r[i]);
+ } catch (err) {
+ // if the generator throws (it could happen in the `keypress`
+ // event), we need to restart it.
+ stream[ESCAPE_DECODER] = emitKeys(stream);
+ stream[ESCAPE_DECODER].next();
+ throw err;
+ }
}
}
} else {Which is still bad because I have no opinion about other changes. Maybe a guarantee that REPL never throws is a good thing. |
|
I think I'd prefer @rlidwka's fix, i.e. to fix it in readline. |
|
Alternative solution was landed in #2107 |
If an error is thrown during the readline
keypressevent, the state of the streaming escape sequence decoder (added in #1601) will become corrupted. This will render the REPL (and possibly your whole terminal) completely unusable. This can be triggered by an object with a custominspectmethod that throws.Originally I modified the escape sequence decoder to avoid corruption but it proved difficult to test because the synchronous throw in
keypresswould end up corrupting the state of the mock streams I was using to test (although for whatever reason it would work with the real TTY streams). Felt too fragile to commit.Instead, I decided that none of the eval machinery should ever throw. This PR adds an extra try/catch around
self.writer(which isutil.inspectby default) and makes some minor cleanups to make error handling more consistent.Note: our test suite currently forbids running any of the REPL machinery in a different tick, which would sidestep most, if not all, of these problems.
cc @rlidwka