-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
64kiB I/O limit after calling redirect_stdout #8789
Comments
If I use (rd, wr) = redirect_stdout()
print(string([1:2^16])) I guess it is just waiting for the buffer to be read (with |
It seems like 64KiB is some default pipe buffer size in libuv? I would be surprised if it can't be made to grow its buffers dynamically as needed; this seems like a severe limitation of its pipes otherwise. Or are external C programs supposed to keep trying to write until space is available in the buffer? This creates a bit of a difficulty (especially as the IJulia task that is supposed to read from the buffer is blocked while external non-threaded C code executes). |
Libuv doesn't have internal buffers, so I assume this is hitting the kernel limit, and the kernel is trying to push back against being requested to copy potentially unlimited amounts of data without an intervening read? |
Why shouldn't the kernel attempt to copy as much information as the user asks it to, until it runs out of memory? |
Is errno set to EAGAIN? We may have requested the kernel to let us know when we are writing data faster than the kernel can get rid of it (by enabling nonblocking io) |
Yes @vtjnash is correct. The libuv buffer size is 64K because that's the default kernel buffer size. The kernel may have given you EAGAIN. |
Yup, Is this desirable behavior? This means that external code in IJulia cannot write more than 64k to stdout. |
It's kind of a catch-22. Since you're reading on the same thread as writing, it's either that or deadlocking your process. Though @vtjnash thinks (and I agree) that this is indeed a bug in our libuv code. |
it's a bug in the libuv code, the process should have deadlocked there instead ("fix" coming shortly) |
See also #8762 Note the pipe limit is only 4k on windows. |
relatedly (somewhat), ye old SIGPIPE bug (#4219) seems to be back again julia> r=Base.Pipe(C_NULL)
Pipe(null, 0 bytes waiting)
julia> w=Base.Pipe(C_NULL)
Pipe(null, 0 bytes waiting)
julia> Base.link_pipe(r,true,w,true)
julia> close(r)
julia> write(w,1)
signal (13): Broken pipe
write at /lib/x86_64-linux-gnu/libpthread.so.0 (unknown line)
unknown function (ip: -512753308)
uv_write2 at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
jl_write_copy at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
jl_putc_copy at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
write at stream.jl:732
write at io.jl:47
jlcall_write;62085 at (unknown line)
unknown function (ip: -513619130)
jl_trampoline at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
unknown function (ip: -513662444)
jl_apply_generic at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
unknown function (ip: -513097098)
unknown function (ip: -513095799)
unknown function (ip: -513092849)
unknown function (ip: -513096751)
unknown function (ip: -513002420)
jl_toplevel_eval at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
jl_toplevel_eval_in at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
jl_f_top_eval at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
eval_user_input at REPL.jl:55
jlcall_eval_user_input;62037 at (unknown line)
unknown function (ip: -513662444)
jl_apply_generic at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
anonymous at task.jl:97
unknown function (ip: -513619130)
jl_trampoline at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
unknown function (ip: -513051537)
unknown function (ip: -513048724)
unknown function (ip: -513050067)
unknown function (ip: -513049969)
jl_handle_stack_switch at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
julia_trampoline at /home/jameson/julia/usr/bin/../lib/libjulia-debug.so (unknown line)
unknown function (ip: 4203654)
__libc_start_main at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
unknown function (ip: 4199593)
unknown function (ip: 0) (this is ubuntu, so signal(13) is SIGPIPE) |
fixed in 0c48dd8 now it'll block in that first write call, like it was supposed to :/ |
So the only way to do this is to have a second thread for reading from stdout? (If that's even possible with libuv...) |
yep. or we can go back to being non-blocking, and then you have to deal with partial writes (libuv does this for us in nonblocking mode) |
I don't think it's reasonable to expect external C libraries to deal with partial writes. |
Note also that there are no guarantees of atomicity for writes over the pipe buffer size, if another thread writes to stdout its output may be interleaved between the pieces of any write greater than the buffer size. |
agreed, but that leaves us where we are now some nice reading: http://linux.die.net/man/7/pipe |
Is this actually ready for backporting? The discussion in 0c48dd8 makes it unclear. |
it should be backported |
Okay it looks like the tests in our fork of libuv weren't updated to account for our changes elsewhere in the library, I think, so maybe it's alright. |
"fix" backported in abaa08e |
Can this be closed now? |
I suppose; it seems like there is not much more we can do about it. |
Via JuliaLang/IJulia.jl#243, I observed this:
Note that the
ccall
returned-1
(EOF error) and the output was truncated to 64kiB.This doesn't seem like desirable behavior. cc: @vtjnash, @Keno, @phlpn
The text was updated successfully, but these errors were encountered: