Skip to content

Commit bd01603

Browse files
committed
readline: fix freeze if keypress event throws
`emitKeys` is a generator which emits `keypress` events in an infinite loop. But if `keypress` event handler throws, the error stops the loop, leaving generator in a broken state. So this patch restarts the generator when an error occures. PR-URL: #2107 Reviewed-By: Christopher Monsanto <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]>
1 parent cf14a24 commit bd01603

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

lib/readline.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,15 @@ function emitKeypressEvents(stream) {
910910
var r = stream[KEYPRESS_DECODER].write(b);
911911
if (r) {
912912
for (var i = 0; i < r.length; i++) {
913-
stream[ESCAPE_DECODER].next(r[i]);
913+
try {
914+
stream[ESCAPE_DECODER].next(r[i]);
915+
} catch (err) {
916+
// if the generator throws (it could happen in the `keypress`
917+
// event), we need to restart it.
918+
stream[ESCAPE_DECODER] = emitKeys(stream);
919+
stream[ESCAPE_DECODER].next();
920+
throw err;
921+
}
914922
}
915923
}
916924
} else {

test/parallel/test-readline-interface.js

+18
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,24 @@ function isWarned(emitter) {
192192
assert.equal(callCount, 1);
193193
rli.close();
194194

195+
// Regression test for repl freeze, #1968:
196+
// check that nothing fails if 'keypress' event throws.
197+
fi = new FakeInput();
198+
rli = new readline.Interface({ input: fi, output: fi, terminal: true });
199+
var keys = [];
200+
fi.on('keypress', function(key) {
201+
keys.push(key);
202+
if (key === 'X') {
203+
throw new Error('bad thing happened');
204+
}
205+
});
206+
try {
207+
fi.emit('data', 'fooX');
208+
} catch(e) { }
209+
fi.emit('data', 'bar');
210+
assert.equal(keys.join(''), 'fooXbar');
211+
rli.close();
212+
195213
// calling readline without `new`
196214
fi = new FakeInput();
197215
rli = readline.Interface({ input: fi, output: fi, terminal: terminal });

0 commit comments

Comments
 (0)