READ from terminal stdin blocks until end of file

56 views
Skip to first unread message

David Banks

unread,
Apr 30, 2011, 9:15:20 AM4/30/11
to mosh-develo...@googlegroups.com
Hi all,

Using the following program 'reader.scm':

#!r6rs

(import (rnrs))

(let loop ()
(let ((datum (read)))
(write datum)
(newline)
(loop)))

I type in some numbers, followed by a newline each time.

amoe@glimworm $ mosh reader.scm
1
2
3
4
[I send EOF with ^D]
1
[^D]
2
[^D]
3
[^D]
4
[^D]
#<eof-object>
...etc.

As you can see the (read) call is blocking until it sees an EOF,
whereas I think it should return and write the result immediately,
like this:

amoe@glimworm $ mosh reader.scm
1
1 [from mosh]
2
2 [from mosh]
.... etc ...

Indeed that's the behaviour that I get from Ikarus and Ypsilon. I'm
not sure if this is a bug as it's probably technically unspecified.
But this behaviour seems quite surprising.

It seems this behaviour only happens at the terminal as it works fine
if I redirect stdin. (If it really had to receive 4 EOFs before
writing output it would presumably hang.)

Cheers,
--
David Banks  <amo...@gmail.com>

okuoku

unread,
Apr 30, 2011, 11:25:25 AM4/30/11
to mosh-develo...@googlegroups.com
2011/4/30 David Banks <amo...@gmail.com>:
> Hi all,
- snip -

> As you can see the (read) call is blocking until it sees an EOF,
> whereas I think it should return and write the result immediately,
> like this:

Reading from terminal is quite un-portable thingy.. and mosh's READ is
optimized aggressively.

If your script requires (REPL like) input prompt, please avoid to use
READ directly and try followings:

1) - Use get-line and buffer input.

(import (rnrs))

(define (string->datum str)
(call-with-port (open-string-input-port str) read))

(define (readline)
(string->datum (get-line (current-input-port))))

(let loop ()
(let ((datum (readline)))
(write datum)
(newline)
(loop)))


2) - POSIX systems and Nmosh only
Recent Nmosh has terminal control functions, so you can enable
char-by-char input like this:

WARNING: you cannot stop this script by CTRL+C

(import (rnrs) (nmosh stubs terminal))

(when (terminal_isatty 0) ;; 0 means stdin
(display "IT'S A TTY!\n")
(terminal_acquire))

(let loop ()
(let ((datum (get-char (current-input-port))))
(write datum)
(newline)
(loop)))
(terminal_release)


I recommend 1) because it's portable (includes other R6RS
implementation) and work as excepted.

David Banks

unread,
Apr 30, 2011, 11:42:58 AM4/30/11
to mosh-develo...@googlegroups.com
On 30 April 2011 16:25, okuoku <oku...@gmail.com> wrote:
> Reading from terminal is quite un-portable thingy.. and mosh's READ is
> optimized aggressively.
>
> If your script requires (REPL like) input prompt, please avoid to use
> READ directly and try followings:
>
> 1) - Use get-line and buffer input.
<snip>

> I recommend 1) because it's portable (includes other R6RS
> implementation) and work as excepted.

ACK, I will do so. Thanks Okuoko.

--
David Banks  <amo...@gmail.com>

Reply all
Reply to author
Forward
0 new messages