-
-
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
Partial blocking reads throw EOFError instead of blocking until read complete (e.g., reading Int from /dev/random) #13559
Comments
BTW, with latest git master, |
It's still there in master at random.jl:35. Interestingly, you can't call it as RandomDevice(unlimited=false)
even though RandomDevice(unlimited=false)
There're definitely things about Julia constructors that I have yet to learn . |
Is the expected behavior a different error? An error is almost certainly assured: "When the entropy pool is empty, reads from /dev/random will block until additional environmental noise is gathered." (http://man7.org/linux/man-pages/man4/random.4.html) |
@hessammehr, that's because specifying the name of the parameter only works when the argument is a keyword argument (after a semicolon in the formal parameter list). |
@pao I was expecting the function to block until all 100 random numbers were ready, and it certainly does block for a while. In fact, it will pause indefinitely if you don't give it any entropy, i.e., don't touch the mouse and keyboard, no network requests, etc. Pressing random keys on the keyboard will cause the function to fail (and sometimes not) and return a partially filled array of random numbers. |
Ah, thanks, that's much clearer. Wonder if that makes this a libuv-related thing? |
That's what I think. It seems to come from iostream.jl:170, which is a ccall, presumably to libuv. |
Correction, Julia's DLLEXPORT uint64_t jl_ios_get_nbyte_int(ios_t *s, const size_t n)
{
assert(n <= 8);
size_t ret = ios_readprep(s, n);
if (ret < n)
throw_eof_error();
.
.
.
|
|
@wildart, I already quoted the man page. |
My bad, I guess a solution should be in different reading mode (blocking and non-blocking) for different deceives. |
The following works fine. rand(RandomDevice(false),Int8, 100) and so does this: a = open("/dev/random", "r")
for i in 1:100
read(a, Int8)
end Both also work with |
This might help understand the problem: #include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
int main() {
printf("sizeof(unsigned long int) = %d\n", sizeof(unsigned long int));
int a = open("/dev/random", O_RDONLY), cnt, ret;
unsigned long int res;
for (cnt=0;cnt<1000;cnt++) {
ret = read(a, (void*) &res, sizeof(long int));
printf("Returned: %d Read:%lu Errno:%s\n", ret, res, strerror(errno));
}
} A typical run of the above code will correctly read 8 bytes per iteration for the first few iterations:
then exhaust /dev/random and start returning 6 bytes per iteration indefinitely, but never less.
A similar thing happens when a = open("/dev/tty1", "r")
for i in 1:100
read(a, Int8)
end |
Is this a valid summary: If Julia performs a partial read, it produces |
Thanks, here's a small revision: "If Julia performs a partial read from a blocking source (e.g. So far I have found that |
@pao Do you think I should revise my first comment so it doesn't confuse people? |
No, I think having the issue history intact is good. Maybe add a note indicating to look further down for the real problem. |
Making the following change at DLLEXPORT uint64_t jl_ios_get_nbyte_int(ios_t *s, const size_t n)
{
assert(n <= 8);
size_t ret = ios_readprep(s, n);
if (ret < n)
throw_eof_error(); to DLLEXPORT uint64_t jl_ios_get_nbyte_int(ios_t *s, const size_t n)
{
assert(n <= 8);
size_t ret = ios_readprep(s, n);
if (ret == 0)
throw_eof_error(); Julia now blocks until the requested number of bytes has been read from the stream, i.e., If |
Could you make a pull request with this change? That would run the full testsuite on it. Can you also check that blocking waiting for more input is consistent with the behaviour described in the docs? Could be good to add a test too. |
@nalimilan The docs are pretty sparse for
readbytes(open("/dev/random","r"), 10, all=true) The above has desired property of blocking until all 10 bytes have been read. Perhaps the random number generator can use |
While it doesn't sound unreasonable to expect both |
I am no expert, but to me the reasonable (least surprising) thing would be for I think we can agree that an |
Blocks until the required number of bytes has been read. Only throws EOFError on actual EOF. Fixes JuliaLang#13559.
Blocks until the required number of bytes has been read. Only throws EOFError on actual EOF. Fixes JuliaLang#13559.
…e identical to baseline.
…e identical to baseline. Fixed infinite loop in previous fix for JuliaLang#13559. Do not throw EOFError if buffer already contains n bytes. JuliaLang#13559
…e identical to baseline. Fixed infinite loop in previous fix for JuliaLang#13559. Do not throw EOFError if buffer already contains n bytes. JuliaLang#13559
…e identical to baseline. Fixed infinite loop in previous fix for JuliaLang#13559. Do not throw EOFError if buffer already contains n bytes. JuliaLang#13559
Uses the qualified path to launch julia
…e identical to baseline. Fixed infinite loop in previous fix for JuliaLang#13559. Do not throw EOFError if buffer already contains n bytes. JuliaLang#13559
Uses the qualified path to launch julia
Looks like a fix for this has been merged? Plz reopen if I'm missing something. |
Uses the qualified path to launch julia (cherry picked from commit 0a79189)
(Look further down for what seems to be the real problem)
Using Julia 0.4.0 on Linux (Ubuntu 14.10 as well as the latest Manjaro)
rand(RandomDevice(false), 100)
almost always fails withEOFError
after the first few numbers.RandomDevice(true)
works flawlessly.The following fails similarly and seems to be how
rand(RandomDevice(false), n)
gets its random data.The text was updated successfully, but these errors were encountered: