From 154a4692dc20df264e8550c8bc4c0fb6ed3d7ca1 Mon Sep 17 00:00:00 2001 From: Sam O'Connor Date: Sun, 17 Jan 2016 10:07:46 +1100 Subject: [PATCH] Fix uv_fs_read() EOF handling. --- base/filesystem.jl | 11 +++++++++-- src/builtins.c | 8 ++++++++ src/jl_uv.c | 9 ++++++--- src/julia.h | 1 + src/sys.c | 9 +-------- test/file.jl | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 58 insertions(+), 13 deletions(-) diff --git a/base/filesystem.jl b/base/filesystem.jl index a6f032ee95844..7f3c9fd36e35d 100644 --- a/base/filesystem.jl +++ b/base/filesystem.jl @@ -158,19 +158,26 @@ function read!(f::File, a::Vector{UInt8}, nel=length(a)) end ret = ccall(:jl_fs_read, Int32, (Int32, Ptr{Void}, Csize_t), f.handle, a, nel) + if ret < nel + throw(EOFError()) + end uv_error("read",ret) return a end nb_available(f::File) = filesize(f) - position(f) +eof(f::File) = nb_available(f) == 0 + function readbytes!(f::File, b::Array{UInt8}, nb=length(b)) nr = min(nb, nb_available(f)) if length(b) < nr resize!(b, nr) end - read!(f, b, nr) - return nr + ret = ccall(:jl_fs_read, Int32, (Int32, Ptr{Void}, Csize_t), + f.handle, b, nr) + uv_error("read",ret) + return ret end read(io::File) = read!(io, Array(UInt8, nb_available(io))) read(io::File, nb::Integer) = read!(io, Array(UInt8, min(nb, nb_available(io)))) diff --git a/src/builtins.c b/src/builtins.c index 50ed9b0a85114..b79a2ac1e2b1b 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -182,6 +182,14 @@ JL_DLLEXPORT void JL_NORETURN jl_bounds_error_ints(jl_value_t *v, size_t *idxs, jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t)); } +JL_DLLEXPORT void JL_NORETURN jl_eof_error(void) +{ + jl_datatype_t *eof_error = + (jl_datatype_t*)jl_get_global(jl_base_module, jl_symbol("EOFError")); + assert(eof_error != NULL); + jl_exceptionf(eof_error, ""); +} + JL_CALLABLE(jl_f_throw) { JL_NARGS(throw, 1, 1); diff --git a/src/jl_uv.c b/src/jl_uv.c index 344356d5a1645..e31d5da8d434a 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -339,9 +339,12 @@ JL_DLLEXPORT int jl_fs_read_byte(int handle) buf[0].len = 1; int ret = uv_fs_read(jl_io_loop, &req, handle, buf, 1, -1, NULL); uv_fs_req_cleanup(&req); - if (ret == -1) - return ret; - return (int)c; + switch (ret) { + case -1: return ret; + case 0: jl_eof_error(); + case 1: return (int)c; + default: assert(0); + } } JL_DLLEXPORT int jl_fs_close(int handle) diff --git a/src/julia.h b/src/julia.h index 2815e4ad52b43..de49880d2fd5b 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1250,6 +1250,7 @@ JL_DLLEXPORT void JL_NORETURN jl_bounds_error_tuple_int(jl_value_t **v, size_t nv, size_t i); JL_DLLEXPORT void JL_NORETURN jl_bounds_error_unboxed_int(void *v, jl_value_t *vt, size_t i); JL_DLLEXPORT void JL_NORETURN jl_bounds_error_ints(jl_value_t *v, size_t *idxs, size_t nidxs); +JL_DLLEXPORT void JL_NORETURN jl_eof_error(void); JL_DLLEXPORT jl_value_t *jl_exception_occurred(void); JL_DLLEXPORT void jl_exception_clear(void); diff --git a/src/sys.c b/src/sys.c index d426e4cbc9a73..270c32858edce 100644 --- a/src/sys.c +++ b/src/sys.c @@ -308,13 +308,6 @@ JL_DLLEXPORT jl_value_t *jl_readuntil(ios_t *s, uint8_t delim) return (jl_value_t*)a; } -static void JL_NORETURN throw_eof_error(void) -{ - jl_datatype_t *eof_error = (jl_datatype_t*)jl_get_global(jl_base_module, jl_symbol("EOFError")); - assert(eof_error != NULL); - jl_exceptionf(eof_error, ""); -} - JL_DLLEXPORT uint64_t jl_ios_get_nbyte_int(ios_t *s, const size_t n) { assert(n <= 8); @@ -323,7 +316,7 @@ JL_DLLEXPORT uint64_t jl_ios_get_nbyte_int(ios_t *s, const size_t n) space = (size_t)(s->size - s->bpos); ret = ios_readprep(s, n); if (space == ret && ret < n) - throw_eof_error(); + jl_eof_error(); } while(ret < n); uint64_t x = 0; uint8_t *buf = (uint8_t*)&s->buf[s->bpos]; diff --git a/test/file.jl b/test/file.jl index 5771c5f80b54f..a28e0e888b46e 100644 --- a/test/file.jl +++ b/test/file.jl @@ -1115,3 +1115,36 @@ end @test copy(DevNull) === DevNull @test eof(DevNull) @test print(DevNull, "go to /dev/null") === nothing + +# Filesystem.File +tmpdir = mktempdir() do d + f = joinpath(d, "test.txt") + open(io->write(io, "123"), f, "w") + f1 = open(f) + f2 = Base.Filesystem.open(f, Base.Filesystem.JL_O_RDONLY) + @test read(f1, UInt8) == read(f2, UInt8) + @test read(f1, UInt8) == read(f2, UInt8) + @test read(f1, UInt8) == read(f2, UInt8) + @test_throws EOFError read(f1, UInt8) + @test_throws EOFError read(f2, UInt8) + close(f1) + close(f2) + + a = UInt8[0,0,0] + f1 = open(f) + f2 = Base.Filesystem.open(f, Base.Filesystem.JL_O_RDONLY) + @test read!(f1, a) == read!(f2, a) + @test_throws EOFError read!(f1, a) + @test_throws EOFError read!(f2, a) + close(f1) + close(f2) + + a = UInt8[0,0,0,0] + f1 = open(f) + f2 = Base.Filesystem.open(f, Base.Filesystem.JL_O_RDONLY) + @test_throws EOFError read!(f1, a) + @test_throws EOFError read!(f2, a) + close(f1) + close(f2) +end +