[MLton] Bug: TextPrimIO does not distinguish between EOF and no
data
Vesa Karvonen
vesa.a.j.k at gmail.com
Wed Dec 12 13:49:31 PST 2007
On Dec 11, 2007 2:17 PM, Ville Laurikari <ville at laurikari.net> wrote:
> I noticed bad behavior with TextIO.canInput. If the input stream has
> no data to read currently but is not yet at EOF, canInput returns
> "SOME 0" instead of NONE. Also, the eof condition is set for the
> stream and all further read attempts fail as if the stream was at EOF.
>
> Attached is a program which demonstrates the problem.
>
> $ mlton bug.sml
> $ (echo foo; sleep 1; echo bar; sleep 1) | ./bug
> foo
> EOF
>
> Expected output would probably be more like this:
> foo
> Would block.
> bar
> Would block.
> EOF
The problem seems to be that the canInput implementation in
basis-library/io/imperative-io.fun does not distinguish between
readArrNB returning NONE (means: eof not seen, any read will block)
and SOME 0 (means: eof seen and at eof).
Below is a patch that seems to fix the problem. With the patch, I get
the following output from the program:
$ (echo foo; sleep 1; echo bar; sleep 1) | ./bug
Would block.
foo
Would block.
bar
Would block.
EOF
-Vesa Karvonen
Index: basis-library/io/imperative-io.fun
===================================================================
--- basis-library/io/imperative-io.fun (revision 6257)
+++ basis-library/io/imperative-io.fun (working copy)
@@ -541,23 +541,27 @@
(* 0 = !first *)
fun loop read =
if read = size
- then read
+ then {read = read, eos = false}
else
let
val slice = AS.slice (buf, read, NONE)
val i = readArrNB slice
in
case i of
- NONE => read
+ NONE => {read = read, eos = false}
| SOME i =>
- if 0 = i then read else loop (read + i)
+ if 0 = i
+ then {read = read, eos = true}
+ else loop (read + i)
end
- val read = loop read
+ val {read, eos} = loop read
val _ = last := read
in
- SOME (if read > 0
- then Int.min (n, read)
- else (state := Open {eos = true}; 0))
+ if read > 0
+ then SOME (Int.min (n, read))
+ else if eos
+ then (state := Open {eos = true}; SOME 0)
+ else NONE
end)
| Stream s => SIO.canInput (s, n)
More information about the MLton
mailing list