www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 10467] New: readln problem with CTRL-Z

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10467

           Summary: readln problem with CTRL-Z
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Phobos
        AssignedTo: nobody puremagic.com
        ReportedBy: bearophile_hugs eml.cc



import std.stdio, std.string;
void main() {
    while (true) {
        write("Input: ");
        string guess = readln.strip;
        if (guess == "1")
            break;
    }
}



On Windows if I run that little program and I insert "1" the program terminates
normally:

dmd -run temp.d
Input: 1 If at the input promtp I give a Ctrl-C it breaks the program:
dmd -run temp.d
Input: ^C If at the input prompt I give a Ctrl-Z the while loop seems to go in an infinite loop:
dmd -run temp.d
Input: ^Z Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: ... -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 24 2013
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10467


monarchdodra gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra gmail.com




 If at the input prompt I give a Ctrl-Z the while loop seems to go in an
 infinite loop:
 
dmd -run temp.d
Input: ^Z Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: Input: ...
Just for the record, what *would* the correct behavior be? The stream is at eof, so stdin has no need to wait for user input, and if you ask for a line, you get "" ... A "correct" program would have either: while (stdin.isOpen && !stdin.eof && !stdin.error) //Meh... Or... string s; while ((s = stdin.readln(line)).length) //very good! Or... char[] line; while (stdin.readln(line)) //very good! For the record, I don't think readln can throw an exception, since the "common semantic" is "read lines until the read fails, then check it failed because you have reached eof"... So... yeah... Doesn't seem like a bug to me, just a program that wasn't designed to handle stdin's eof... -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10467






 Just for the record, what *would* the correct behavior be?
An equivalent Python2.6 program: while True: guess = raw_input("Input: ").strip() if guess == "1": break This is how Python behaves here (inputs are 1, CTRL-C and CTRL-Z):
temp.py
Input: 1
temp.py
Input: Traceback (most recent call last): File "\temp.py", line 2, in <module> guess = raw_input("Input: ").strip() KeyboardInterrupt
temp.py
Input: ^Z Traceback (most recent call last): File "\temp.py", line 2, in <module> guess = raw_input("Input: ").strip() EOFError -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10467




Elsewhere monarch_dodra adds some more comments on this topic and a link:

 I don't think this is a bug (I replied on the bug report): 
 terminating the stream doesn't mean terminating the program, 
 and if the program doesn't know how to handle a 
 closed/eof/error'd stdin, it will just loop...

 This FAQ link explains it pretty well for C++, which is pretty 
 much the same thing as in D:
 http://www.parashift.com/c++-faq/stream-input-failure.html
 (the next few points are relevant too).

 We could argue the design isn't optimal, yes, but it's not 
 bugged.
-- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 24 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=10467






 
 Just for the record, what *would* the correct behavior be?
An equivalent Python2.6 program: while True: guess = raw_input("Input: ").strip() if guess == "1": break This is how Python behaves here (inputs are 1, CTRL-C and CTRL-Z):
temp.py
Input: 1
temp.py
Input: Traceback (most recent call last): File "\temp.py", line 2, in <module> guess = raw_input("Input: ").strip() KeyboardInterrupt
temp.py
Input: ^Z Traceback (most recent call last): File "\temp.py", line 2, in <module> guess = raw_input("Input: ").strip() EOFError
I'm noticing D's readln doesn't quite have the same semantics as C++'s: In C++, getline will keep reading until it *can* read at least a single non empty line, trying again if it reads an empty line. This means that you can't know if you'll succeed unless you try. getline explicitly returns the state of the stream, so you can test the return status of getline. D's getline, on the other hand, returns empty lines. This means there is no real way to check for success, unless an exception was thrown, or the stream is in an error state. This means the interface is kind of crummy, since it claims: "returns: 0 for end of file, otherwise number of characters read": which sucks, since it can succeed if 0 characters were read... Also, D's readln says "StdioException on I/O error". So after a second though, I think you are right, and Python's "throw for reads of EOF" is not only safer and better, but also works, and is the *documented behavior*... too bad we didn't have this for C++ :'( -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 25 2013