diff options
author | Andrew Clayton <a.clayton@nginx.com> | 2024-01-29 11:35:13 +0000 |
---|---|---|
committer | Andrew Clayton <a.clayton@nginx.com> | 2024-02-21 16:20:32 +0000 |
commit | ac3a54d67181bb8bfbe6753058941c91dd200c63 (patch) | |
tree | 80ffa344a4405d8551e484c781b4d289a9c6b2c1 | |
parent | 79c817724799a3c6ce88693b188926b4e626807f (diff) | |
download | unit-ac3a54d67181bb8bfbe6753058941c91dd200c63.tar.gz unit-ac3a54d67181bb8bfbe6753058941c91dd200c63.tar.bz2 |
Wasm-wc: Improve request buffer handling
When Unit receives a request, if the body of that request is greater
than a certain amount (16KiB by default) then it is written to a
temporary file.
When a language module goes to read the request body in such situations
it will end up using read(2).
The wasm-wasi-component language module was failing to properly read
request bodies of around 2GiB or more.
This is because (on Linux at least) read(2) (and other related system
calls) will only read (or write) at most 0x7ffff000 (2,147,479,552)
bytes, this is the case for both 32 and 64-bit systems.
Regardless, it's probably not a good idea doing IO in such large chunks
anyway.
This patch changes the wasm-wasi-component language module to read the
request buffer in 32MiB chunks (this matches the original 'wasm'
language module).
We are still limited to a 4GiB address space and can only upload files a
little under 4GiB.
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
-rw-r--r-- | src/wasm-wasi-component/src/lib.rs | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/src/wasm-wasi-component/src/lib.rs b/src/wasm-wasi-component/src/lib.rs index da78ea6e..032878f5 100644 --- a/src/wasm-wasi-component/src/lib.rs +++ b/src/wasm-wasi-component/src/lib.rs @@ -495,14 +495,21 @@ impl NxtRequestInfo { fn request_read(&mut self, dst: &mut BytesMut) { unsafe { let rest = dst.spare_capacity_mut(); - let amt = bindings::nxt_unit_request_read( - self.info, - rest.as_mut_ptr().cast(), - rest.len(), - ); + let mut total_bytes_read = 0; + loop { + let amt = bindings::nxt_unit_request_read( + self.info, + rest.as_mut_ptr().wrapping_add(total_bytes_read).cast(), + 32 * 1024 * 1024, + ); + total_bytes_read += amt as usize; + if total_bytes_read >= rest.len() { + break; + } + } // TODO: handle failure when `amt` is negative - let amt: usize = amt.try_into().unwrap(); - dst.set_len(dst.len() + amt); + let total_bytes_read: usize = total_bytes_read.try_into().unwrap(); + dst.set_len(dst.len() + total_bytes_read); } } |