-
Notifications
You must be signed in to change notification settings - Fork 71
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
Eio.Path.load loads only first 4gb on big files #335
Comments
Can confirm:
My first suspicion was not using 64bits off_t, but it seems it is, at some point someone is storing it in 32bit. |
The bug seems to be internal to libuv:
the caller is result = read(req->file, req->bufs[0].base, req->bufs[0].len);
printf("%s:%d result=%zd len=%zd\n", __func__, __LINE__, result, req->bufs[0].len); |
We're actually passing a 2^32 buffer, somehow it turns into 0, somewhere must be wrapping around, anyway it's late.
10 bucks it's a literal int overflow |
So the bug seems to be in luv, we pass the correct number, but libuv gets a very likely overflowed int.
|
|
It might be time to start discussing a community fork of luv if we ever want to see that fixed. |
Yes, we also have an unstable ABI with uring (I've hit two kernel bugs the last week). I also don't think luv offers much other than portability with windows, there had been talks about just writing a pure backend that is at least POSIX and windows can eat cake until IOCP is done. |
Did some quick tests in Eio and it fixes that case: See ocaml-multicore/eio#335 There are probably more spots (outside iovec) where a (s)size_t is wrongly expressed as an Unsigned.UInt, ideally it should always be a Long.
We can work around this in eio_luv quite easily by limiting the amount we ask libuv to read in one go to 2GB. It's unlikely it would do more than that anyway, and the caller will handle it like any other short read. |
It's done here: e2f38d3, needs some ironing out and maybe I should pull that out of that PR. |
A separate PR would be great! |
Luv uses a 32 bit int for buffer sizes and wraps if the value passed is too big. In particular, a request for to read 4GB of data is interpreted as a request for 0 bytes. Fixes ocaml-multicore#335.
Luv uses a 32 bit int for buffer sizes and wraps if the value passed is too big. In particular, a request for to read 4GB of data is interpreted as a request for 0 bytes. Fixes ocaml-multicore#335.
Luv uses a 32 bit int for buffer sizes and wraps if the value passed is too big. In particular, a request for to read 4GB of data is interpreted as a request for 0 bytes. Fixes ocaml-multicore#335.
I'm using the Luv backend and when trying to load a file bigger than 4gb's the result string always ends up being the first 4gb's of the file.
The text was updated successfully, but these errors were encountered: