From 7005d29514b05391947727285636ff7f4558bb1e Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Mon, 25 May 2015 22:08:04 +0200 Subject: [PATCH] stream: fix `select()` race condition Call `uv__read()`/`uv__write()` before re-entering `select` thread. Otherwise we might get second event from it, and will block indefinitely on `uv__read()`/`uv__write()`. Fix: https://github.com/libuv/libuv/issues/304 PR-URL: https://github.com/libuv/libuv/pull/365 Reviewed-By: Ben Noordhuis --- src/unix/stream.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/unix/stream.c b/src/unix/stream.c index 48827b65..8e4a06e6 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -231,7 +231,6 @@ static void uv__stream_osx_select_cb(uv_async_t* handle) { /* Get and reset stream's events */ events = s->events; ACCESS_ONCE(int, s->events) = 0; - uv_sem_post(&s->async_sem); assert(events != 0); assert(events == (events & (UV__POLLIN | UV__POLLOUT))); @@ -242,6 +241,14 @@ static void uv__stream_osx_select_cb(uv_async_t* handle) { if ((events & UV__POLLOUT) && uv__io_active(&stream->io_watcher, UV__POLLOUT)) uv__stream_io(stream->loop, &stream->io_watcher, UV__POLLOUT); + + if (stream->flags & UV_CLOSING) + return; + + /* NOTE: It is important to do it here, otherwise `select()` might be called + * before the actual `uv__read()`, leading to the blocking syscall + */ + uv_sem_post(&s->async_sem); }