How should I handle uv_read_cb's nread < 0
Closed this issue · 12 comments
I called uv_read_stop and it caused an assertion failure at the following assert on Linux. I thought I might called uv_read_stop at a wrong time. So please tell me calling it at what situations will cause the failure and when should I call it.
v0.11
int uv_read_stop(uv_stream_t* stream) {
/* Sanity check. We're going to stop the handle unless it's primed for
* writing but that means there should be some kind of write action in
* progress.
*/
assert(!uv__io_active(&stream->io_watcher, UV__POLLOUT) ||
!QUEUE_EMPTY(&stream->write_completed_queue) ||
!QUEUE_EMPTY(&stream->write_queue) ||
stream->shutdown_req != NULL ||
stream->connect_req != NULL);
When a stream's EOF reached, calling uv_read_stop will cause this assert failure. But if I uv_shutdown the stream then, calling uv_read_stop won't cause that assert. So if the read callback was called with nread < 0, it won't be called any more and I shouldn't use uv_read_stop in that situation, just uv_close is required. Am I right?
Yes, at least that is how I implemented it in my wrapper.
I'd need to look a bit deeper, we might need to handle it better.
If EOF is reached the stream automatically stops reading: https://github.com/joyent/libuv/blob/master/src/unix/stream.c#L947-L954, not so if there has been another type of error: https://github.com/joyent/libuv/blob/master/src/unix/stream.c#L1118-L1121 In the latter case, not stopping or closing the handle will trigger that other assert.
Also, uv_close
ends up calling uv_read_stop
. Can you paste a backtrace?
Which traceback, the assertion failure? The assertion failure is just inside uv_read_stop according to the gdb backtrace when assertion failure. That happened when I call uv_read_stop after the read callback got an EOF. I think uv_read_stop should return an error code instead of an assertion failure which breaks the program.
And if I didn't call uv_close, another assertion failure will be caused according to the another type of error @saghul mentioned, so I must make sure uv_close called when the read callback got an error. Am I right?
Yes, the backtrace. I wonder why this doesn't fail when you do uv_close: https://github.com/joyent/libuv/blob/master/src/unix/stream.c#L1549
so I must make sure uv_close called when the read callback got an error. Am I right?
YEah. IDeally uv_read_stop is enough... excpt when it isn't.
I think uv_read_stop should return an error code instead of an assertion failure which breaks the program.
I'd rather have it silently do nothing instead.
I think backtrace won't help a lot. I will add a printf to print the values later.
IDeally uv_read_stop is enough... excpt when it isn't.
I think it just should help the user close the handle if the user didn't do it instead causing an assertion failure.
Closing, libuv/libuv#47 landed, so now you won't need to do anything, the handle stops itself.