linux: close streams without an extra read (#3250)
This commit is contained in:
parent
14f6c4cc1f
commit
9f0101dcb8
@ -1516,25 +1516,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
*/
|
||||
pe->events &= w->pevents | POLLERR | POLLHUP;
|
||||
|
||||
/* Work around an epoll quirk where it sometimes reports just the
|
||||
* EPOLLERR or EPOLLHUP event. In order to force the event loop to
|
||||
* move forward, we merge in the read/write events that the watcher
|
||||
* is interested in; uv__read() and uv__write() will then deal with
|
||||
* the error or hangup in the usual fashion.
|
||||
*
|
||||
* Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user
|
||||
* reads the available data, calls uv_read_stop(), then sometime later
|
||||
* calls uv_read_start() again. By then, libuv has forgotten about the
|
||||
* hangup and the kernel won't report EPOLLIN again because there's
|
||||
* nothing left to read. If anything, libuv is to blame here. The
|
||||
* current hack is just a quick bandaid; to properly fix it, libuv
|
||||
* needs to remember the error/hangup event. We should get that for
|
||||
* free when we switch over to edge-triggered I/O.
|
||||
*/
|
||||
if (pe->events == POLLERR || pe->events == POLLHUP)
|
||||
pe->events |=
|
||||
w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
|
||||
|
||||
if (pe->events != 0) {
|
||||
/* Run signal watchers last. This also affects child process watchers
|
||||
* because those are implemented in terms of signal watchers.
|
||||
|
||||
@ -60,6 +60,12 @@ void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
if (events & UV__POLLRDHUP)
|
||||
pevents |= UV_DISCONNECT;
|
||||
|
||||
/* On error or hangup, mix in events the user is interested in so the
|
||||
* appropriate read/write callbacks are invoked. */
|
||||
if (events & (POLLERR | POLLHUP))
|
||||
pevents |=
|
||||
w->pevents & (UV_READABLE | UV_PRIORITIZED | UV_WRITABLE | UV_DISCONNECT);
|
||||
|
||||
handle->poll_cb(handle, 0, pevents);
|
||||
}
|
||||
|
||||
|
||||
@ -1218,16 +1218,15 @@ void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
* operating systems, devices like PTYs sometimes produce partial reads even
|
||||
* when more data is available.
|
||||
*/
|
||||
if ((events & POLLHUP) &&
|
||||
if ((events & (POLLHUP | UV__POLLRDHUP)) &&
|
||||
!(events & POLLIN) &&
|
||||
(stream->flags & UV_HANDLE_READING) &&
|
||||
!(stream->flags & UV_HANDLE_READ_EOF)) {
|
||||
uv_buf_t buf = { NULL, 0 };
|
||||
uv__stream_eof(stream, &buf);
|
||||
}
|
||||
|
||||
if (uv__stream_fd(stream) == -1)
|
||||
return; /* read_cb closed stream. */
|
||||
}
|
||||
|
||||
if (events & (POLLOUT | POLLERR | POLLHUP)) {
|
||||
uv__write(stream);
|
||||
|
||||
@ -178,7 +178,11 @@ void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) {
|
||||
handle = container_of(w, uv_udp_t, io_watcher);
|
||||
assert(handle->type == UV_UDP);
|
||||
|
||||
if (revents & POLLIN)
|
||||
/* Trigger a recv and send to find out what POLLERR occurred. */
|
||||
if (revents & POLLERR)
|
||||
revents |= POLLIN | POLLOUT;
|
||||
|
||||
if (revents & (POLLIN | POLLERR))
|
||||
uv__udp_recvmsg(handle, 0);
|
||||
|
||||
/* Just Linux support for now. */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user