I have a Julia function that needs to readline(stdin)
in a non-blocking way. When I try to use the bytesavailable(stdin)
function, it always returns 0, even when there are data ready to read. If anyone has some insight into this, I would greatly appreciate your suggestions.
Below is an example. I am using Julia version 1.11.3.
# Test bytesavailable(stdin)
# Create a pipe
(rd, wr) = redirect_stdin()
# Write to the write end of the pipe
write(wr, "test 1\n")
write(wr, "test 2\n")
flush(wr) # Make sure the data is written
bytesavailable(stdin) # returns 0
bytesavailable(rd) # returns 0
eof(rd) # returns false
readline(stdin) # "test 1"
readline(rd) # "test 2"
# Close the pipe
close(rd)
close(wr)
The method bytesavailable
is, at best, a hint that readavailable
uses internally. The documentation on bytesavailable
is sparse, but the documentation for readavailable
says:
Read available buffered data from a stream. Actual I/O is performed only if no data has already been buffered...
There is an additional warning:
The amount of data returned is implementation-dependent; for example it can depend on the internal choice of buffer size. Other functions such as
read
should generally be used instead.
The key is the "buffered data" bit. The stdin
constant is not implemented in Julia as a buffered stream of any kind: in fact, it isn't implemented in Julia at all, and is instead implemented using the libuv
C library to abstract away the OS-specific stuff. It is likely that whoever implemented terminal stream communication in Julia did not want to try to figure out the internals of every possible OS's implementation of standard input to determine if it is buffered and what that buffer size is, so bytesavailable
returning 0
just tells you that any read from stdin
might reach out to the OS.
bytesavailable
should probably not be used as an indication of whether the IO object is ready to read anything. If you want to read from stdin
in a way that is guaranteed to be non-blocking, consider spawning a separate Task
with @async
that reads and pushes the data into a Channel
.