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;
}

Reply via email to