Skip to content

Commit 5fbf28b

Browse files
committed
Merge pull request #13638 from hessammehr/master
More efficient fix for #13559.
2 parents df78cfa + 9ef2949 commit 5fbf28b

File tree

2 files changed

+75
-3
lines changed

2 files changed

+75
-3
lines changed

src/sys.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,13 @@ static void NORETURN throw_eof_error(void)
310310
DLLEXPORT uint64_t jl_ios_get_nbyte_int(ios_t *s, const size_t n)
311311
{
312312
assert(n <= 8);
313-
size_t ret = ios_readprep(s, n);
314-
if (ret < n)
315-
throw_eof_error();
313+
size_t space, ret;
314+
do {
315+
space = s->size - s->bpos;
316+
ret = ios_readprep(s, n);
317+
if (space == ret && ret < n)
318+
throw_eof_error();
319+
} while(ret < n);
316320
uint64_t x = 0;
317321
uint8_t *buf = (uint8_t*)&s->buf[s->bpos];
318322
if (n == 8) {

test/file.jl

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,3 +922,71 @@ test_12992()
922922
test2_12992()
923923
test2_12992()
924924
test2_12992()
925+
926+
# issue 13559
927+
928+
function test_13559()
929+
fn = tempname()
930+
run(`mkfifo $fn`)
931+
# use subprocess to write 127 bytes to FIFO
932+
writer_cmds = "x=open(\"$fn\", \"w\"); for i=1:127 write(x,0xaa); flush(x); sleep(0.1) end; close(x); quit()"
933+
open(`$(Base.julia_cmd()) -e $writer_cmds`)
934+
#quickly read FIFO, draining it and blocking but not failing with EOFError yet
935+
r = open(fn, "r")
936+
# 15 proper reads
937+
for i=1:15
938+
@test read(r, Int64) == -6148914691236517206
939+
end
940+
# last read should throw EOFError when FIFO closes, since there are only 7 bytes available.
941+
@test_throws EOFError read(r, Int64)
942+
close(r)
943+
rm(fn)
944+
end
945+
@unix_only test_13559()
946+
947+
function test_read_nbyte()
948+
fn = tempname()
949+
# Write one byte. One byte read should work once
950+
# but 2-byte read should throw EOFError.
951+
f = open(fn, "w+") do f
952+
write(f, 0x55)
953+
flush(f)
954+
seek(f, 0)
955+
@test read(f, UInt8) == 0x55
956+
@test_throws EOFError read(f, UInt8)
957+
seek(f, 0)
958+
@test_throws EOFError read(f, UInt16)
959+
end
960+
# Write 2 more bytes. Now 2-byte read should work once
961+
# but 4-byte read should fail with EOFError.
962+
open(fn, "a+") do f
963+
write(f, 0x4444)
964+
flush(f)
965+
seek(f, 0)
966+
@test read(f, UInt16) == 0x4455
967+
@test_throws EOFError read(f, UInt16)
968+
seek(f,0)
969+
@test_throws EOFError read(f, UInt32)
970+
end
971+
# Write 4 more bytes. Now 4-byte read should work once
972+
# but 8-byte read should fail with EOFError.
973+
open(fn, "a+") do f
974+
write(f, 0x33333333)
975+
flush(f)
976+
seek(f, 0)
977+
@test read(f, UInt32) == 0x33444455
978+
@test_throws EOFError read(f, UInt32)
979+
seek(f,0)
980+
@test_throws EOFError read(f, UInt64)
981+
end
982+
# Writing one more byte should allow an 8-byte
983+
# read to proceed.
984+
open(fn, "a+") do f
985+
write(f, 0x22)
986+
flush(f)
987+
seek(f, 0)
988+
@test read(f, UInt64) == 0x2233333333444455
989+
end
990+
rm(fn)
991+
end
992+
test_read_nbyte()

0 commit comments

Comments
 (0)