diff --git a/src/unix/stream.c b/src/unix/stream.c index 86a179b35..7513b9100 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -929,12 +929,16 @@ static void uv__write_callbacks(uv_stream_t* stream) { static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { + uv_read_cb read_cb; + stream->flags |= UV_HANDLE_READ_EOF; - stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); - stream->read_cb(stream, UV_EOF, buf); + read_cb = stream->read_cb; + stream->read_cb = NULL; + stream->alloc_cb = NULL; + read_cb(stream, UV_EOF, buf); } @@ -1037,11 +1041,7 @@ static void uv__read(uv_stream_t* stream) { is_ipc = stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) stream)->ipc; - /* XXX: Maybe instead of having UV_HANDLE_READING we just test if - * tcp->read_cb is NULL or not? - */ while (stream->read_cb - && (stream->flags & UV_HANDLE_READING) && (count-- > 0)) { assert(stream->alloc_cb != NULL); @@ -1084,7 +1084,7 @@ static void uv__read(uv_stream_t* stream) { /* Error */ if (errno == EAGAIN || errno == EWOULDBLOCK) { /* Wait for the next one. */ - if (stream->flags & UV_HANDLE_READING) { + if (stream->read_cb != NULL) { uv__io_start(stream->loop, &stream->io_watcher, POLLIN); uv__stream_osx_interrupt_select(stream); } @@ -1098,8 +1098,9 @@ static void uv__read(uv_stream_t* stream) { /* Error. User should call uv_close(). */ stream->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); stream->read_cb(stream, UV__ERR(errno), &buf); - if (stream->flags & UV_HANDLE_READING) { - stream->flags &= ~UV_HANDLE_READING; + if (stream->read_cb != NULL) { + stream->read_cb = NULL; + stream->alloc_cb = NULL; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); @@ -1222,7 +1223,7 @@ void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { */ if ((events & (POLLHUP | UV__POLLRDHUP)) && !(events & POLLIN) && - (stream->flags & UV_HANDLE_READING) && + (stream->read_cb != NULL) && !(stream->flags & UV_HANDLE_READ_EOF)) { uv_buf_t buf = { NULL, 0 }; uv__stream_eof(stream, &buf); @@ -1459,9 +1460,6 @@ int uv__read_start(uv_stream_t* stream, assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || stream->type == UV_TTY); - /* The UV_HANDLE_READING flag is irrelevant of the state of the stream - it - * just expresses the desired state of the user. */ - stream->flags |= UV_HANDLE_READING; stream->flags &= ~UV_HANDLE_READ_EOF; /* TODO: try to do the read inline? */ @@ -1480,10 +1478,9 @@ int uv__read_start(uv_stream_t* stream, int uv_read_stop(uv_stream_t* stream) { - if (!(stream->flags & UV_HANDLE_READING)) + if (stream->read_cb == NULL) return 0; - stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); diff --git a/src/uv-common.c b/src/uv-common.c index ac738be1f..8d8745044 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -949,8 +949,13 @@ int uv_read_start(uv_stream_t* stream, if (stream->flags & UV_HANDLE_CLOSING) return UV_EINVAL; - if (stream->flags & UV_HANDLE_READING) +#ifdef _WIN32 + if (stream->flags & UV_HANDLE_READING) + return UV_EALREADY; +#else + if (stream->read_cb != NULL) return UV_EALREADY; +#endif if (!(stream->flags & UV_HANDLE_READABLE)) return UV_ENOTCONN;