Bug #21188
closed
PRISM does not end reading from tty with ^D twice
Description
When reading from tty, ^D
ends the text without the newline.
$ cat
a
Typing ^D
here, only "a" is sent without a newline, and cat
echos back it.
Then by typing ^D
again, an empty read that means EOF causes cat
to exit.
ruby --parser=parse.y
behaves in this manner:
$ ruby --parser=parse.y
p __FILE__"-"
Typing ^D
twice just after __FILE__
, and p
prints "-"
.
However prism requires ^D
thrice.
Updated by hsbt (Hiroshi SHIBATA) 4 months ago
- Status changed from Open to Assigned
Updated by tenderlovemaking (Aaron Patterson) about 9 hours ago
- Status changed from Assigned to Closed
Applied in changeset git|89d89fa49d387a09e0d3ea7092a598b88d6d86eb.
When reading from stdin, put a wrapper around the IO object
The purpose of this commit is to fix Bug #21188. We need to detect when
stdin has run in to an EOF case. Unfortunately we can't call the eof
function on IO because it will block.
Here is a short script to demonstrate the issue:
x = STDIN.gets
puts x
puts x.eof?
If you run the script, then type some characters (but NOT a newline),
then hit Ctrl-D twice, it will print the input string. Unfortunately,
calling eof?
will try to read from STDIN again causing us to need a
3rd Ctrl-D to exit the program.
Before introducing the EOF callback to Prism, the input loop looked
kind of like this:
loop do
str = STDIN.gets
process(str)
if str.nil?
p :DONE
end
end
Which required 3 Ctrl-D to exit. If we naively changed it to something
like this:
loop do
str = STDIN.gets
process(str)
if STDIN.eof?
p :DONE
end
end
It would still require 3 Ctrl-D because eof?
would block. In this
patch, we're wrapping the IO object, checking the buffer for a newline
and length, and then using that to simulate a non-blocking eof? method.
This commit wraps STDIN and emulates a non-blocking eof
function.
[Bug #21188]