From 536c5f8661af4b57f8cc8be43bf482ae27a9fcd8 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 8 Jun 2013 03:14:32 +0200 Subject: [PATCH 1/4] unix: clear UV_STREAM_SHUTTING after shutdown() Fix a state machine buglet where the UV_STREAM_SHUTTING flag didn't get cleared. --- src/unix/stream.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/unix/stream.c b/src/unix/stream.c index 4d846f6a..ae2e6a04 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -630,6 +630,7 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { static void uv__drain(uv_stream_t* stream) { uv_shutdown_t* req; + int status; assert(ngx_queue_empty(&stream->write_queue)); uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); @@ -642,21 +643,17 @@ static void uv__drain(uv_stream_t* stream) { req = stream->shutdown_req; stream->shutdown_req = NULL; + stream->flags &= ~UV_STREAM_SHUTTING; uv__req_unregister(stream->loop, req); - if (shutdown(uv__stream_fd(stream), SHUT_WR)) { - /* Error. Report it. User should call uv_close(). */ + status = shutdown(uv__stream_fd(stream), SHUT_WR); + if (status) uv__set_sys_error(stream->loop, errno); - if (req->cb) { - req->cb(req, -1); - } - } else { - uv__set_sys_error(stream->loop, 0); - ((uv_handle_t*) stream)->flags |= UV_STREAM_SHUT; - if (req->cb) { - req->cb(req, 0); - } - } + else + stream->flags |= UV_STREAM_SHUT; + + if (req->cb != NULL) + req->cb(req, status); } } From 12210fe578623995d13cc5126427c1c67de4b6e0 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 8 Jun 2013 03:20:29 +0200 Subject: [PATCH 2/4] unix: fix busy loop, write if POLLERR or POLLHUP This fixes a busy loop by working around a quirk with Linux kernels <= 2.6.32 where an EPIPE or ECONNRESET error on a file descriptor that is polled for EPOLLOUT but not EPOLLIN gets reported by epoll_wait() as just EPOLLERR|EPOLLHUP, like this: epoll_wait(5, {{EPOLLERR|EPOLLHUP, {u32=12, u64=12}}}, 1024, 433) = 1 Before this commit, libuv called uv__read() which attempts to read from the file descriptor. With newer kernels and on other operating systems that fails like this: read(12, "", 65536) = -1 EPIPE (Broken pipe) Which tells libuv there is a connection error and it should notify the user of that. On the affected Linux kernels however, the read succeeds with an EOF: read(12, "", 65536) = 0 Which is subsequently passed on to the user. In most cases, the user will close the handle and everything is fine. Node.js however sometimes keeps the handle open in an attempt to flush pending write requests. While libuv doesn't officially support this, unofficially it works... ...except on those older kernels. Because the kernel keeps waking up the event loop without setting POLLOUT and because the read calls EOF but don't error, libuv's I/O state machine doesn't progress. That's why this commit changes uv__stream_io() to also write pending data. While the read() system call doesn't error, the write() system call will. Fixes joyent/node#5504. --- src/unix/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/stream.c b/src/unix/stream.c index ae2e6a04..c9df9797 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -1118,7 +1118,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { return; /* read_cb closed stream. */ } - if (events & UV__POLLOUT) { + if (events & (UV__POLLOUT | UV__POLLERR | UV__POLLHUP)) { assert(uv__stream_fd(stream) >= 0); uv__write(stream); uv__write_callbacks(stream); From c3b75406a66a10222a589cb173e8f469e9665c7e Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 12 Jun 2013 21:52:01 +0200 Subject: [PATCH 3/4] 2013.06.13, Version 0.10.11 (Stable) Changes since version 0.10.10: * unix: unconditionally stop handle on close (Ben Noordhuis) * freebsd: don't enable dtrace if it's not available (Brian White) * build: make HAVE_DTRACE=0 should disable dtrace (Timothy J. Fontaine) * unix: remove overzealous assert (Ben Noordhuis) * unix: clear UV_STREAM_SHUTTING after shutdown() (Ben Noordhuis) * unix: fix busy loop, write if POLLERR or POLLHUP (Ben Noordhuis) --- ChangeLog | 17 +++++++++++++++++ src/version.c | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 840dde22..f62839e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2013.06.13, Version 0.10.11 (Stable) + +Changes since version 0.10.10: + +* unix: unconditionally stop handle on close (Ben Noordhuis) + +* freebsd: don't enable dtrace if it's not available (Brian White) + +* build: make HAVE_DTRACE=0 should disable dtrace (Timothy J. Fontaine) + +* unix: remove overzealous assert (Ben Noordhuis) + +* unix: clear UV_STREAM_SHUTTING after shutdown() (Ben Noordhuis) + +* unix: fix busy loop, write if POLLERR or POLLHUP (Ben Noordhuis) + + 2013.06.05, Version 0.10.10 (Stable), 0d95a88bd35fce93863c57a460be613aea34d2c5 Changes since version 0.10.9: diff --git a/src/version.c b/src/version.c index d101eace..248ff284 100644 --- a/src/version.c +++ b/src/version.c @@ -35,7 +35,7 @@ #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 10 #define UV_VERSION_PATCH 11 -#define UV_VERSION_IS_RELEASE 0 +#define UV_VERSION_IS_RELEASE 1 #define UV_VERSION ((UV_VERSION_MAJOR << 16) | \ From 72e440d7e193123c0359fa12a7fabab15d7d9f51 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 12 Jun 2013 21:52:05 +0200 Subject: [PATCH 4/4] Now working on v0.10.12 --- ChangeLog | 2 +- src/version.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index f62839e3..0935b246 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -2013.06.13, Version 0.10.11 (Stable) +2013.06.13, Version 0.10.11 (Stable), c3b75406a66a10222a589cb173e8f469e9665c7e Changes since version 0.10.10: diff --git a/src/version.c b/src/version.c index 248ff284..b09c926b 100644 --- a/src/version.c +++ b/src/version.c @@ -34,8 +34,8 @@ #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 10 -#define UV_VERSION_PATCH 11 -#define UV_VERSION_IS_RELEASE 1 +#define UV_VERSION_PATCH 12 +#define UV_VERSION_IS_RELEASE 0 #define UV_VERSION ((UV_VERSION_MAJOR << 16) | \