unix: don't malloc on sync uv_fs_read (#4162)

We can use the |bufs| argument directly instead of always copying it
and sometimes heap-allocating it.

The same trick doesn't work for uv_fs_write() because the iterator
mutates the buffers in the list and that's visible to the caller.

Fixes: https://github.com/libuv/libuv/issues/4038
This commit is contained in:
Ben Noordhuis 2023-10-12 20:40:18 +02:00 committed by GitHub
parent 75f7de4010
commit 13148457a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -441,9 +441,10 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
iov = (const struct iovec*) req->bufs;
result = uv__fs_read_do(req->file, iov, req->nbufs, req->off);
/* Early cleanup of bufs allocation, since we're done with it. */
if (req->bufs != req->bufsml)
uv__free(req->bufs);
/* We don't own the buffer list in the synchronous case. */
if (req->cb != NULL)
if (req->bufs != req->bufsml)
uv__free(req->bufs);
req->bufs = NULL;
req->nbufs = 0;
@ -1871,9 +1872,14 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
if (bufs == NULL || nbufs == 0)
return UV_EINVAL;
req->off = off;
req->file = file;
req->bufs = (uv_buf_t*) bufs; /* Safe, doesn't mutate |bufs| */
req->nbufs = nbufs;
if (cb == NULL)
goto post;
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs));
@ -1883,12 +1889,10 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
req->off = off;
if (cb != NULL)
if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 1))
return 0;
if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 1))
return 0;
post:
POST;
}