I noticed that libuv v1.x (963ecc82) in Windows 10, the
'uv_read_start' on a 'uv_tty_t' fails when provided with a small
buffer which cannot contain the data being read.
I also noticed that it calls the callbacks many times providing
smaller and smaller portions.
I attached an example that illustrates this scenario.
In the following output we get the "unknown error" for the case where
I provide as much characters as the buffer size (254 characters, plus
2 for the line break)
```
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=256)
libuv_ttyreadpeacemeal.c:51:main(server started!)
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
libuv_ttyreadpeacemeal.c:18:on_read(nread=85)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=171)
libuv_ttyreadpeacemeal.c:18:on_read(nread=57)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=114)
libuv_ttyreadpeacemeal.c:18:on_read(nread=38)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=76)
libuv_ttyreadpeacemeal.c:18:on_read(nread=25)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=51)
libuv_ttyreadpeacemeal.c:18:on_read(nread=17)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=34)
libuv_ttyreadpeacemeal.c:18:on_read(nread=11)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=23)
libuv_ttyreadpeacemeal.c:18:on_read(nread=7)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=16)
libuv_ttyreadpeacemeal.c:18:on_read(nread=5)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=11)
libuv_ttyreadpeacemeal.c:18:on_read(nread=3)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=8)
libuv_ttyreadpeacemeal.c:18:on_read(nread=2)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=6)
libuv_ttyreadpeacemeal.c:18:on_read(nread=2)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=4)
libuv_ttyreadpeacemeal.c:18:on_read(nread=1)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=3)
libuv_ttyreadpeacemeal.c:18:on_read(nread=1)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=2)
libuv_ttyreadpeacemeal.c:15:on_read(error=unknown error)
```
However, if I provide fewer characters (251 characters, plus 2 for the
line break), everything goes fine:
```
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=256)
libuv_ttyreadpeacemeal.c:51:main(server started!)
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
libuv_ttyreadpeacemeal.c:18:on_read(nread=85)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=171)
libuv_ttyreadpeacemeal.c:18:on_read(nread=57)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=114)
libuv_ttyreadpeacemeal.c:18:on_read(nread=38)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=76)
libuv_ttyreadpeacemeal.c:18:on_read(nread=25)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=51)
libuv_ttyreadpeacemeal.c:18:on_read(nread=17)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=34)
libuv_ttyreadpeacemeal.c:18:on_read(nread=11)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=23)
libuv_ttyreadpeacemeal.c:18:on_read(nread=7)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=16)
libuv_ttyreadpeacemeal.c:18:on_read(nread=5)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=11)
libuv_ttyreadpeacemeal.c:18:on_read(nread=3)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=8)
libuv_ttyreadpeacemeal.c:18:on_read(nread=2)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=6)
libuv_ttyreadpeacemeal.c:18:on_read(nread=2)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=4)
libuv_ttyreadpeacemeal.c:18:on_read(nread=1)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=3)
```
Just for comparison, in Linux the output is (254 characters, plus 1
for the line break):
```
libuv_ttyreadpeacemeal.c:51:main(server started!)
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=256)
libuv_ttyreadpeacemeal.c:18:on_read(nread=256)
libuv_ttyreadpeacemeal.c:29:on_alloc(provided_size=0)
libuv_ttyreadpeacemeal.c:15:on_read(error=no buffer space available)
```
Is this expected? Am I doing something wrong?
Thanks in advance.
--
Renato Maia
--
You received this message because you are subscribed to the Google Groups
"libuv" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/libuv/CAB-PuDqgPd2GSE%2B42WHP2dqR%3DSL3TfwPu0rLEH9r_5Hfzpcftg%40mail.gmail.com.
#include <assert.h>
#include <uv.h>
#define BUFFER_SIZE 256
#define log(F,V) printf("%s:%d:%s("F")\n", __FILE__, __LINE__, __func__, V);
typedef struct DataRead {
char buffer[BUFFER_SIZE];
size_t count;
} DataRead;
static void on_read (uv_stream_t *stream, ssize_t nread, const uv_buf_t *buffer)
{
if (nread < 0) {
log("error=%s", uv_strerror(nread));
} else {
DataRead *data_read = (DataRead *)stream->data;
log("nread=%zd", nread);
data_read->count += nread;
}
}
static void on_alloc (uv_handle_t *handle, size_t suggested_size, uv_buf_t
*buffer)
{
DataRead *data_read = (DataRead *)handle->data;
assert(data_read);
buffer->base = data_read->buffer + data_read->count;
buffer->len = BUFFER_SIZE - data_read->count;
log("provided_size=%ld", buffer->len);
}
int main(int argc, char const *argv[])
{
uv_loop_t loop;
uv_tty_t stdin_tty;
DataRead data_read;
int err;
data_read.count = 0;
err = uv_loop_init(&loop);
assert(err >= 0);
err = uv_tty_init(&loop, &stdin_tty, 0, 0);
assert(err >= 0);
stdin_tty.data = &data_read; /* 'uv_read_start' calls 'on_alloc'
before it returns! */
err = uv_read_start((uv_stream_t *)&stdin_tty, on_alloc, on_read);
assert(err >= 0);
log("%s", "server started!");
err = uv_run(&loop, UV_RUN_DEFAULT);
assert(err >= 0);
return 0;
}