Skip to content

Commit

Permalink
Fix uv_fs_read() EOF handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
samoconnor committed Jan 20, 2016
1 parent fccce37 commit 154a469
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 13 deletions.
11 changes: 9 additions & 2 deletions base/filesystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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))))
Expand Down
8 changes: 8 additions & 0 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 6 additions & 3 deletions src/jl_uv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
9 changes: 1 addition & 8 deletions src/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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];
Expand Down
33 changes: 33 additions & 0 deletions test/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 154a469

Please sign in to comment.