diff --git a/src/libuv/.gitignore b/src/libuv/.gitignore
index d6c65dba..3f4c5193 100644
--- a/src/libuv/.gitignore
+++ b/src/libuv/.gitignore
@@ -12,6 +12,9 @@ vgcore.*
 /libuv.so
 /libuv.dylib
 
+# Generated by dtrace(1) when doing an in-tree build.
+/src/unix/uv-dtrace.h
+
 /out/
 /build/gyp
 
diff --git a/src/libuv/.mailmap b/src/libuv/.mailmap
index 2d98623b..5dc4075e 100644
--- a/src/libuv/.mailmap
+++ b/src/libuv/.mailmap
@@ -1,13 +1,17 @@
-# update AUTHORS with:
-#   git log --all --reverse --format='%aN <%aE>' | perl -ne 'BEGIN{print "# Authors ordered by first contribution.\n"} print unless $h{$_}; $h{$_} = 1' > AUTHORS
-<rm@joyent.com> <rm@fingolfin.org>
-<ryan@joyent.com> <ry@tinyclouds.org>
-<bertbelder@gmail.com> <info@2bs.nl>
-<alan@prettyrobots.com> <alan@blogometer.com>
-San-Tai Hsu <vanilla@fatpipi.com>
-Isaac Z. Schlueter <i@izs.me>
-Saúl Ibarra Corretgé <saghul@gmail.com>
-Yuki OKUMURA <mjt@cltn.org>
+Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
+Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
+Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
+Brandon Philips <brandon.philips@rackspace.com> <brandon@ifup.org>
+Brian White <mscdex@mscdex.net>
+Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
 Frank Denis <github@pureftpd.org>
+Isaac Z. Schlueter <i@izs.me>
+Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
+Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
 Ryan Emery <seebees@gmail.com>
+San-Tai Hsu <vanilla@fatpipi.com>
+Saúl Ibarra Corretgé <saghul@gmail.com>
+Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
+Timothy J. Fontaine <tjfontaine@gmail.com>
 Yasuhiro Matsumoto <mattn.jp@gmail.com>
+Yuki Okumura <mjt@cltn.org>
diff --git a/src/libuv/AUTHORS b/src/libuv/AUTHORS
index d28143bb..119773a5 100644
--- a/src/libuv/AUTHORS
+++ b/src/libuv/AUTHORS
@@ -28,7 +28,7 @@ Marek Jelen <marek@jelen.biz>
 Fedor Indutny <fedor.indutny@gmail.com>
 Saúl Ibarra Corretgé <saghul@gmail.com>
 Felix Geisendörfer <felix@debuggable.com>
-Yuki OKUMURA <mjt@cltn.org>
+Yuki Okumura <mjt@cltn.org>
 Roman Shtylman <shtylman@gmail.com>
 Frank Denis <github@pureftpd.org>
 Carter Allen <CarterA@opt-6.com>
@@ -44,7 +44,6 @@ Dan VerWeire <dverweire@gmail.com>
 Brandon Benvie <brandon@bbenvie.com>
 Brandon Philips <brandon.philips@rackspace.com>
 Nathan Rajlich <nathan@tootallnate.net>
-Brandon Philips <brandon@ifup.org>
 Charlie McConnell <charlie@charlieistheman.com>
 Vladimir Dronnikov <dronnikov@gmail.com>
 Aaron Bieber <qbit@deftly.net>
@@ -54,8 +53,35 @@ Erik Dubbelboer <erik@dubbelboer.com>
 Keno Fischer <kenof@stanford.edu>
 Ira Cooper <Ira.Cooper@mathworks.com>
 Andrius Bentkus <andrius.bentkus@gmail.com>
-Brian White <mscdex@gmail.com>
 Iñaki Baz Castillo <ibc@aliax.net>
 Mark Cavage <mark.cavage@joyent.com>
 George Yohng <georgegh@oss3d.com>
 Xidorn Quan <quanxunzhen@gmail.com>
+Roman Neuhauser <rneuhauser@suse.cz>
+Shuhei Tanuma <shuhei.tanuma@gmail.com>
+Bryan Cantrill <bcantrill@acm.org>
+Trond Norbye <trond.norbye@gmail.com>
+Tim Holy <holy@wustl.edu>
+Prancesco Pertugio <meh@schizofreni.co>
+Leonard Hecker <leonard.hecker91@gmail.com>
+Andrew Paprocki <andrew@ishiboo.com>
+Luigi Grilli <luigi.grilli@gmail.com>
+Shannen Saez <shannenlaptop@gmail.com>
+Artur Adib <arturadib@gmail.com>
+Hiroaki Nakamura <hnakamur@gmail.com>
+Ting-Yu Lin <ph.minamo@cytisan.com>
+Stephen Gallagher <sgallagh@redhat.com>
+Shane Holloway <shane.holloway@ieee.org>
+Andrew Shaffer <darawk@gmail.com>
+Vlad Tudose <vlad.tudose@intel.com>
+Ben Leslie <benno@benno.id.au>
+Tim Bradshaw <tfb@cley.com>
+Timothy J. Fontaine <tjfontaine@gmail.com>
+Marc Schlaich <marc.schlaich@googlemail.com>
+Brian Mazza <louseman@gmail.com>
+Nils Maier <maierman@web.de>
+Nicholas Vavilov <vvnicholas@gmail.com>
+Miroslav Bajtoš <miro.bajtos@gmail.com>
+Elliot Saba <staticfloat@gmail.com>
+Wynn Wilkes <wynnw@movenetworks.com>
+Andrei Sedoi <bsnote@gmail.com>
diff --git a/src/libuv/ChangeLog b/src/libuv/ChangeLog
new file mode 100644
index 00000000..6ffffc77
--- /dev/null
+++ b/src/libuv/ChangeLog
@@ -0,0 +1,225 @@
+2013.07.26, Version 0.10.13 (Stable)
+
+Changes since version 0.10.12:
+
+* unix, windows: fix uv_fs_chown() function prototype (Ben Noordhuis)
+
+
+2013.07.10, Version 0.10.12 (Stable), 58a46221bba726746887a661a9f36fe9ff204209
+
+Changes since version 0.10.11:
+
+* linux: add support for MIPS (Andrei Sedoi)
+
+* windows: uv_spawn shouldn't reject reparse points (Bert Belder)
+
+* windows: use WSAGetLastError(), not errno (Ben Noordhuis)
+
+* build: darwin: disable -fstrict-aliasing warnings (Ben Noordhuis)
+
+* build: `all` now builds static and dynamic lib (Ben Noordhuis)
+
+* unix: fix build when !defined(PTHREAD_MUTEX_ERRORCHECK) (Ben Noordhuis)
+
+
+2013.06.13, Version 0.10.11 (Stable), c3b75406a66a10222a589cb173e8f469e9665c7e
+
+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:
+
+* include: document uv_update_time() and uv_now() (Ben Noordhuis)
+
+* linux: fix cpu model parsing on newer arm kernels (Ben Noordhuis)
+
+* linux: fix memory leak in uv_cpu_info() error path (Ben Noordhuis)
+
+* linux: don't ignore OOM errors in uv_cpu_info() (Ben Noordhuis)
+
+* unix, windows: move uv_now() to uv-common.c (Ben Noordhuis)
+
+* darwin: make uv_fs_sendfile() respect length param (Wynn Wilkes)
+
+
+2013.05.29, Version 0.10.9 (Stable), a195f9ace23d92345baf57582678bfc3017e6632
+
+Changes since version 0.10.8:
+
+* unix: fix stream refcounting buglet (Ben Noordhuis)
+
+* unix: remove erroneous asserts (Ben Noordhuis)
+
+* unix: add uv__is_closing() macro (Ben Noordhuis)
+
+* unix: stop stream POLLOUT watcher on write error (Ben Noordhuis)
+
+
+2013.05.25, Version 0.10.8 (Stable), 0f39be12926fe2d8766a9f025797a473003e6504
+
+Changes since version 0.10.7:
+
+* windows: make uv_spawn not fail under job control (Bert Belder)
+
+* darwin: assume CFRunLoopStop() isn't thread-safe (Fedor Indutny)
+
+* win: fix UV_EALREADY incorrectly set (Bert Belder)
+
+* darwin: make two uv__cf_*() functions static (Ben Noordhuis)
+
+* darwin: task_info() cannot fail (Ben Noordhuis)
+
+* unix: add mapping for ENETDOWN (Ben Noordhuis)
+
+* unix: implicitly signal write errors to libuv user (Ben Noordhuis)
+
+* unix: fix assert on signal pipe overflow (Bert Belder)
+
+* unix: turn off POLLOUT after stream connect (Ben Noordhuis)
+
+
+2013.05.15, Version 0.10.7 (Stable), 028baaf0846b686a81e992cb2f2f5a9b8e841fcf
+
+Changes since version 0.10.6:
+
+* windows: kill child processes when the parent dies (Bert Belder)
+
+
+2013.05.15, Version 0.10.6 (Stable), 11e6613e6260d95c8cf11bf89a2759c24649319a
+
+Changes since version 0.10.5:
+
+* stream: fix osx select hack (Fedor Indutny)
+
+* stream: fix small nit in select hack, add test (Fedor Indutny)
+
+* build: link with libkvm on openbsd (Ben Noordhuis)
+
+* stream: use harder sync restrictions for osx-hack (Fedor Indutny)
+
+* unix: fix EMFILE error handling (Ben Noordhuis)
+
+* darwin: fix unnecessary include headers (Daisuke Murase)
+
+* darwin: rename darwin-getproctitle.m (Ben Noordhuis)
+
+* build: convert predefined $PLATFORM to lower case (Elliot Saba)
+
+* build: set soname in shared library (Ben Noordhuis)
+
+* build: make `make test` link against .a again (Ben Noordhuis)
+
+* darwin: fix ios build, don't require ApplicationServices (Ben Noordhuis)
+
+* build: only set soname on shared object builds (Timothy J. Fontaine)
+
+
+2013.04.24, Version 0.10.5 (Stable), 6595a7732c52eb4f8e57c88655f72997a8567a67
+
+Changes since version 0.10.4:
+
+* unix: silence STATIC_ASSERT compiler warnings (Ben Noordhuis)
+
+* windows: make timers handle large timeouts (Miroslav Bajtoš)
+
+* windows: remove superfluous assert statement (Bert Belder)
+
+* unix: silence STATIC_ASSERT compiler warnings (Ben Noordhuis)
+
+* linux: don't use fopen() in uv_resident_set_memory() (Ben Noordhuis)
+
+
+2013.04.12, Version 0.10.4 (Stable), 85827e26403ac6dfa331af8ec9916ea7e27bd833
+
+Changes since version 0.10.3:
+
+* include: update uv_backend_fd() documentation (Ben Noordhuis)
+
+* unix: include uv.h in src/version.c (Ben Noordhuis)
+
+* unix: don't write more than IOV_MAX iovecs (Fedor Indutny)
+
+* mingw-w64: don't call _set_invalid_parameter_handler (Nils Maier)
+
+* build: gyp disable thin archives (Timothy J. Fontaine)
+
+* sunos: re-export entire library when static (Timothy J. Fontaine)
+
+* unix: dtrace probes for tick-start and tick-stop (Timothy J. Fontaine)
+
+* windows: fix memory leak in fs__sendfile (Shannen Saez)
+
+* windows: remove double initialization in uv_tty_init (Shannen Saez)
+
+* build: fix dtrace-enabled out of tree build (Ben Noordhuis)
+
+* build: squelch -Wdollar-in-identifier-extension warnings (Ben Noordhuis)
+
+* inet: snprintf returns int, not size_t (Brian White)
+
+* win: refactor uv_cpu_info (Bert Belder)
+
+* build: add support for Visual Studio 2012 (Nicholas Vavilov)
+
+* build: -Wno-dollar-in-identifier-extension is clang only (Ben Noordhuis)
+
+
+2013.03.28, Version 0.10.3 (Stable), 31ebe23973dd98fd8a24c042b606f37a794e99d0
+
+Changes since version 0.10.2:
+
+* include: remove extraneous const from uv_version() (Ben Noordhuis)
+
+* doc: update README, replace `OS` by `PLATFORM` (Ben Noordhuis)
+
+* build: simplify .buildstamp rule (Ben Noordhuis)
+
+* build: disable -Wstrict-aliasing on darwin (Ben Noordhuis)
+
+* darwin: don't select(&exceptfds) in fallback path (Ben Noordhuis)
+
+* unix: don't clear flags after closing UDP handle (Saúl Ibarra Corretgé)
+
+
+2013.03.25, Version 0.10.2 (Stable), 0f36a00568f3e7608f97f6c6cdb081f4800a50c9
+
+This is the first officially versioned release of libuv. Starting now
+libuv will make releases independently of Node.js.
+
+Changes since Node.js v0.10.0:
+
+* test: add tap output for windows (Timothy J. Fontaine)
+
+* unix: fix uv_tcp_simultaneous_accepts() logic (Ben Noordhuis)
+
+* include: bump UV_VERSION_MINOR (Ben Noordhuis)
+
+* unix: improve uv_guess_handle() implementation (Ben Noordhuis)
+
+* stream: run try_select only for pipes and ttys (Fedor Indutny)
+
+Changes since Node.js v0.10.1:
+
+* build: rename OS to PLATFORM (Ben Noordhuis)
+
+* unix: make uv_timer_init() initialize repeat (Brian Mazza)
+
+* unix: make timers handle large timeouts (Ben Noordhuis)
+
+* build: add OBJC makefile var (Ben Noordhuis)
+
+* Add `uv_version()` and `uv_version_string()` APIs (Bert Belder)
diff --git a/src/libuv/README.md b/src/libuv/README.md
index cdddbd2a..54740ca9 100644
--- a/src/libuv/README.md
+++ b/src/libuv/README.md
@@ -64,7 +64,7 @@ To build via Makefile simply execute:
 
 MinGW users should run this instead:
 
-    make OS=mingw
+    make PLATFORM=mingw
 
 Out-of-tree builds are supported:
 
diff --git a/src/libuv/build.mk b/src/libuv/build.mk
index 91886f0e..6cba169f 100644
--- a/src/libuv/build.mk
+++ b/src/libuv/build.mk
@@ -18,17 +18,21 @@
 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 # IN THE SOFTWARE.
 
-OS ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
+ifdef PLATFORM
+override PLATFORM := $(shell echo $(PLATFORM) | tr "[A-Z]" "[a-z]")
+else
+PLATFORM = $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
+endif
 
 CPPFLAGS += -I$(SRCDIR)/include -I$(SRCDIR)/include/uv-private
 
-ifeq (darwin,$(OS))
+ifeq (darwin,$(PLATFORM))
 SOEXT = dylib
 else
 SOEXT = so
 endif
 
-ifneq (,$(findstring mingw,$(OS)))
+ifneq (,$(findstring mingw,$(PLATFORM)))
 include $(SRCDIR)/config-mingw.mk
 else
 include $(SRCDIR)/config-unix.mk
@@ -88,6 +92,7 @@ TESTS= \
 	test/test-loop-stop.o \
 	test/test-multiple-listen.o \
 	test/test-mutexes.o \
+	test/test-osx-select.o \
 	test/test-pass-always.o \
 	test/test-ping-pong.o \
 	test/test-pipe-bind-error.o \
@@ -125,6 +130,7 @@ TESTS= \
 	test/test-threadpool.o \
 	test/test-threadpool-cancel.o \
 	test/test-timer-again.o \
+	test/test-timer-from-check.o \
 	test/test-timer.o \
 	test/test-tty.o \
 	test/test-udp-dgram-too-big.o \
@@ -137,20 +143,16 @@ TESTS= \
 	test/test-util.o \
 	test/test-walk-handles.o \
 
-all: libuv.a
+.PHONY: all bench clean clean-platform distclean test
 
-run-tests$(E): test/run-tests.o test/runner.o $(RUNNER_SRC) $(TESTS) libuv.$(SOEXT)
+run-tests$(E): test/run-tests.o test/runner.o $(RUNNER_SRC) $(TESTS) libuv.a
 	$(CC) $(CPPFLAGS) $(RUNNER_CFLAGS) -o $@ $^ $(RUNNER_LIBS) $(RUNNER_LDFLAGS)
 
-run-benchmarks$(E): test/run-benchmarks.o test/runner.o $(RUNNER_SRC) $(BENCHMARKS) libuv.$(SOEXT)
+run-benchmarks$(E): test/run-benchmarks.o test/runner.o $(RUNNER_SRC) $(BENCHMARKS) libuv.a
 	$(CC) $(CPPFLAGS) $(RUNNER_CFLAGS) -o $@ $^ $(RUNNER_LIBS) $(RUNNER_LDFLAGS)
 
 test/echo.o: test/echo.c test/echo.h
 
-
-.PHONY: clean clean-platform distclean test bench
-
-
 test: run-tests$(E)
 	$(CURDIR)/$<
 
diff --git a/src/libuv/checksparse.sh b/src/libuv/checksparse.sh
index f06b27d2..7412c21c 100755
--- a/src/libuv/checksparse.sh
+++ b/src/libuv/checksparse.sh
@@ -222,7 +222,7 @@ SunOS)
   ;;
 esac
 
-for ARCH in __i386__ __x86_64__ __arm__; do
+for ARCH in __i386__ __x86_64__ __arm__ __mips__; do
   $SPARSE $SPARSE_FLAGS -D$ARCH=1 $SOURCES
 done
 
diff --git a/src/libuv/common.gypi b/src/libuv/common.gypi
index 8c6c8875..67291fdc 100644
--- a/src/libuv/common.gypi
+++ b/src/libuv/common.gypi
@@ -36,6 +36,7 @@
         },
         'xcode_settings': {
           'GCC_OPTIMIZATION_LEVEL': '0',
+          'OTHER_CFLAGS': [ '-Wno-strict-aliasing' ],
         },
         'conditions': [
           ['OS != "win"', {
@@ -132,6 +133,11 @@
       [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
         'cflags': [ '-Wall' ],
         'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ],
+        'target_conditions': [
+          ['_type=="static_library"', {
+            'standalone_static_library': 1, # disable thin archive which needs binutils >= 2.19
+          }],
+        ],
         'conditions': [
           [ 'host_arch != target_arch and target_arch=="ia32"', {
             'cflags': [ '-m32' ],
@@ -192,6 +198,11 @@
           }],
         ],
       }],
+     ['OS=="solaris"', {
+       'cflags': [ '-fno-omit-frame-pointer' ],
+       # pull in V8's postmortem metadata
+       'ldflags': [ '-Wl,-z,allextract' ]
+     }],
     ],
   },
 }
diff --git a/src/libuv/config-mingw.mk b/src/libuv/config-mingw.mk
index 400a6c46..84df27a1 100644
--- a/src/libuv/config-mingw.mk
+++ b/src/libuv/config-mingw.mk
@@ -35,7 +35,7 @@ RUNNER_LDFLAGS=$(LDFLAGS)
 RUNNER_LIBS=-lws2_32 -lpsapi -liphlpapi
 RUNNER_SRC=test/runner-win.c
 
-libuv.a: $(WIN_OBJS) src/fs-poll.o src/inet.o src/uv-common.o
+libuv.a: $(WIN_OBJS) src/fs-poll.o src/inet.o src/uv-common.o src/version.o
 	$(AR) rcs $@ $^
 
 src/%.o: src/%.c include/uv.h include/uv-private/uv-win.h
diff --git a/src/libuv/config-unix.mk b/src/libuv/config-unix.mk
index efe0d17e..d230bb25 100644
--- a/src/libuv/config-unix.mk
+++ b/src/libuv/config-unix.mk
@@ -29,7 +29,10 @@ CPPFLAGS += -D_FILE_OFFSET_BITS=64
 
 RUNNER_SRC=test/runner-unix.c
 RUNNER_CFLAGS=$(CFLAGS) -I$(SRCDIR)/test
-RUNNER_LDFLAGS=-L"$(CURDIR)" -luv -Xlinker -rpath -Xlinker "$(CURDIR)"
+RUNNER_LDFLAGS=
+
+DTRACE_OBJS=
+DTRACE_HEADER=
 
 OBJS += src/unix/async.o
 OBJS += src/unix/core.o
@@ -53,27 +56,38 @@ OBJS += src/unix/udp.o
 OBJS += src/fs-poll.o
 OBJS += src/uv-common.o
 OBJS += src/inet.o
+OBJS += src/version.o
 
-ifeq (sunos,$(OS))
+ifeq (sunos,$(PLATFORM))
+HAVE_DTRACE ?= 1
 CPPFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
 LDFLAGS+=-lkstat -lnsl -lsendfile -lsocket
 # Library dependencies are not transitive.
-RUNNER_LDFLAGS += $(LDFLAGS)
 OBJS += src/unix/sunos.o
+ifeq (1, $(HAVE_DTRACE))
+OBJS += src/unix/dtrace.o
+DTRACE_OBJS += src/unix/core.o
+endif
 endif
 
-ifeq (aix,$(OS))
+ifeq (aix,$(PLATFORM))
 CPPFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500
 LDFLAGS+= -lperfstat
 OBJS += src/unix/aix.o
 endif
 
-ifeq (darwin,$(OS))
+ifeq (darwin,$(PLATFORM))
+HAVE_DTRACE ?= 1
+# dtrace(1) probes contain dollar signs on OS X. Mute the warnings they
+# generate but only when CC=clang, -Wno-dollar-in-identifier-extension
+# is a clang extension.
+ifeq (__clang__,$(shell sh -c "$(CC) -dM -E - </dev/null | grep -ow __clang__"))
+CFLAGS += -Wno-dollar-in-identifier-extension
+endif
 CPPFLAGS += -D_DARWIN_USE_64_BIT_INODE=1
 LDFLAGS += -framework Foundation \
            -framework CoreServices \
-           -framework ApplicationServices \
-           -dynamiclib -install_name "@rpath/libuv.dylib"
+           -framework ApplicationServices
 SOEXT = dylib
 OBJS += src/unix/darwin.o
 OBJS += src/unix/kqueue.o
@@ -82,7 +96,7 @@ OBJS += src/unix/proctitle.o
 OBJS += src/unix/darwin-proctitle.o
 endif
 
-ifeq (linux,$(OS))
+ifeq (linux,$(PLATFORM))
 CSTDFLAG += -D_GNU_SOURCE
 LDFLAGS+=-ldl -lrt
 RUNNER_CFLAGS += -D_GNU_SOURCE
@@ -92,49 +106,72 @@ OBJS += src/unix/linux-core.o \
         src/unix/proctitle.o
 endif
 
-ifeq (freebsd,$(OS))
+ifeq (freebsd,$(PLATFORM))
+ifeq ($(shell dtrace -l 1>&2 2>/dev/null; echo $$?),0)
+HAVE_DTRACE ?= 1
+endif
 LDFLAGS+=-lkvm
 OBJS += src/unix/freebsd.o
 OBJS += src/unix/kqueue.o
 endif
 
-ifeq (dragonfly,$(OS))
+ifeq (dragonfly,$(PLATFORM))
 LDFLAGS+=-lkvm
 OBJS += src/unix/freebsd.o
 OBJS += src/unix/kqueue.o
 endif
 
-ifeq (netbsd,$(OS))
+ifeq (netbsd,$(PLATFORM))
 LDFLAGS+=-lkvm
 OBJS += src/unix/netbsd.o
 OBJS += src/unix/kqueue.o
 endif
 
-ifeq (openbsd,$(OS))
+ifeq (openbsd,$(PLATFORM))
 LDFLAGS+=-lkvm
 OBJS += src/unix/openbsd.o
 OBJS += src/unix/kqueue.o
 endif
 
-ifneq (,$(findstring cygwin,$(OS)))
+ifneq (,$(findstring cygwin,$(PLATFORM)))
 # We drop the --std=c89, it hides CLOCK_MONOTONIC on cygwin
 CSTDFLAG = -D_GNU_SOURCE
 LDFLAGS+=
 OBJS += src/unix/cygwin.o
 endif
 
-ifeq (sunos,$(OS))
+ifeq (sunos,$(PLATFORM))
 RUNNER_LDFLAGS += -pthreads
 else
 RUNNER_LDFLAGS += -pthread
 endif
 
+ifeq ($(HAVE_DTRACE), 1)
+DTRACE_HEADER = src/unix/uv-dtrace.h
+CPPFLAGS += -Isrc/unix
+CFLAGS += -DHAVE_DTRACE
+endif
+
+ifneq (darwin,$(PLATFORM))
+# Must correspond with UV_VERSION_MAJOR and UV_VERSION_MINOR in src/version.c
+SO_LDFLAGS = -Wl,-soname,libuv.so.0.10
+endif
+
+RUNNER_LDFLAGS += $(LDFLAGS)
+
+all:
+	# Force a sequential build of the static and the shared library.
+	# Works around a make quirk where it forgets to (re)build either
+	# the *.o or *.pic.o files, depending on what target comes first.
+	$(MAKE) -f $(SRCDIR)/Makefile libuv.a
+	$(MAKE) -f $(SRCDIR)/Makefile libuv.$(SOEXT)
+
 libuv.a: $(OBJS)
 	$(AR) rcs $@ $^
 
 libuv.$(SOEXT):	override CFLAGS += -fPIC
 libuv.$(SOEXT):	$(OBJS:%.o=%.pic.o)
-	$(CC) -shared -o $@ $^ $(LDFLAGS)
+	$(CC) -shared -o $@ $^ $(LDFLAGS) $(SO_LDFLAGS)
 
 include/uv-private/uv-unix.h: \
 	include/uv-private/uv-bsd.h \
@@ -145,10 +182,10 @@ include/uv-private/uv-unix.h: \
 src/unix/internal.h: src/unix/linux-syscalls.h
 
 src/.buildstamp src/unix/.buildstamp test/.buildstamp:
-	mkdir -p $(dir $@)
+	mkdir -p $(@D)
 	touch $@
 
-src/unix/%.o src/unix/%.pic.o: src/unix/%.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h src/unix/.buildstamp
+src/unix/%.o src/unix/%.pic.o: src/unix/%.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h src/unix/.buildstamp $(DTRACE_HEADER)
 	$(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
 
 src/%.o src/%.pic.o: src/%.c include/uv.h include/uv-private/uv-unix.h src/.buildstamp
@@ -158,7 +195,13 @@ test/%.o: test/%.c include/uv.h test/.buildstamp
 	$(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
 
 clean-platform:
-	$(RM) test/run-{tests,benchmarks}.dSYM $(OBJS) $(OBJS:%.o=%.pic.o)
+	$(RM) test/run-{tests,benchmarks}.dSYM $(OBJS) $(OBJS:%.o=%.pic.o) src/unix/uv-dtrace.h
+
+src/unix/uv-dtrace.h: src/unix/uv-dtrace.d
+	dtrace -h -xnolibs -s $< -o $@
+
+src/unix/dtrace.o: src/unix/uv-dtrace.d $(DTRACE_OBJS)
+	dtrace -G -s $^ -o $@
 
-%.pic.o %.o:  %.m
-	$(CC) $(CPPFLAGS) $(CFLAGS) -c $^ -o $@
+src/unix/dtrace.pic.o: src/unix/uv-dtrace.d $(DTRACE_OBJS:%.o=%.pic.o)
+	dtrace -G -s $^ -o $@
diff --git a/src/libuv/gyp_uv b/src/libuv/gyp_uv
index ab594515..651bd095 100755
--- a/src/libuv/gyp_uv
+++ b/src/libuv/gyp_uv
@@ -24,6 +24,7 @@ def host_arch():
   if machine == 'i386': return 'ia32'
   if machine == 'x86_64': return 'x64'
   if machine.startswith('arm'): return 'arm'
+  if machine.startswith('mips'): return 'mips'
   return machine  # Return as-is and hope for the best.
 
 
diff --git a/src/libuv/include/uv-private/uv-unix.h b/src/libuv/include/uv-private/uv-unix.h
index 729082e0..9e83cd88 100644
--- a/src/libuv/include/uv-private/uv-unix.h
+++ b/src/libuv/include/uv-private/uv-unix.h
@@ -300,8 +300,8 @@ typedef struct {
   void* buf;                                                                  \
   size_t len;                                                                 \
   off_t off;                                                                  \
-  uid_t uid;                                                                  \
-  gid_t gid;                                                                  \
+  uv_uid_t uid;                                                               \
+  uv_gid_t gid;                                                               \
   double atime;                                                               \
   double mtime;                                                               \
   struct uv__work work_req;                                                   \
diff --git a/src/libuv/include/uv.h b/src/libuv/include/uv.h
index de375d4b..3978def5 100644
--- a/src/libuv/include/uv.h
+++ b/src/libuv/include/uv.h
@@ -47,7 +47,7 @@ extern "C" {
 
 
 #define UV_VERSION_MAJOR 0
-#define UV_VERSION_MINOR 9
+#define UV_VERSION_MINOR 10
 
 
 #if defined(_MSC_VER) && _MSC_VER < 1600
@@ -228,6 +228,20 @@ typedef enum {
 } uv_run_mode;
 
 
+/*
+ * Returns the libuv version packed into a single integer. 8 bits are used for
+ * each component, with the patch number stored in the 8 least significant
+ * bits. E.g. for libuv 1.2.3 this would return 0x010203.
+ */
+UV_EXTERN unsigned int uv_version(void);
+
+/*
+ * Returns the libuv version number as a string. For non-release versions
+ * "-pre" is appended, so the version number could be "1.2.3-pre".
+ */
+UV_EXTERN const char* uv_version_string(void);
+
+
 /*
  * This function must be called before any other functions in libuv.
  *
@@ -273,15 +287,36 @@ UV_EXTERN void uv_stop(uv_loop_t*);
 UV_EXTERN void uv_ref(uv_handle_t*);
 UV_EXTERN void uv_unref(uv_handle_t*);
 
+/*
+ * Update the event loop's concept of "now". Libuv caches the current time
+ * at the start of the event loop tick in order to reduce the number of
+ * time-related system calls.
+ *
+ * You won't normally need to call this function unless you have callbacks
+ * that block the event loop for longer periods of time, where "longer" is
+ * somewhat subjective but probably on the order of a millisecond or more.
+ */
 UV_EXTERN void uv_update_time(uv_loop_t*);
+
+/*
+ * Return the current timestamp in milliseconds. The timestamp is cached at
+ * the start of the event loop tick, see |uv_update_time()| for details and
+ * rationale.
+ *
+ * The timestamp increases monotonically from some arbitrary point in time.
+ * Don't make assumptions about the starting point, you will only get
+ * disappointed.
+ *
+ * Use uv_hrtime() if you need sub-milliseond granularity.
+ */
 UV_EXTERN uint64_t uv_now(uv_loop_t*);
 
 /*
  * Get backend file descriptor. Only kqueue, epoll and event ports are
  * supported.
  *
- * This can be used in conjunction with uv_run_once() to poll in one thread and
- * run the event loop's event callbacks in another.
+ * This can be used in conjunction with `uv_run(loop, UV_RUN_NOWAIT)` to
+ * poll in one thread and run the event loop's event callbacks in another.
  *
  * Useful for embedding libuv's event loop in another event loop.
  * See test/test-embed.c for an example.
@@ -660,12 +695,12 @@ UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,
                                unsigned int delay);
 
 /*
- * This setting applies to Windows only.
  * Enable/disable simultaneous asynchronous accept requests that are
  * queued by the operating system when listening for new tcp connections.
  * This setting is used to tune a tcp server for the desired performance.
  * Having simultaneous accepts can significantly improve the rate of
- * accepting connections (which is why it is enabled by default).
+ * accepting connections (which is why it is enabled by default) but
+ * may lead to uneven load distribution in multi-process setups.
  */
 UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);
 
@@ -1607,10 +1642,10 @@ UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file,
     int mode, uv_fs_cb cb);
 
 UV_EXTERN int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path,
-    int uid, int gid, uv_fs_cb cb);
+    uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
 
 UV_EXTERN int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file,
-    int uid, int gid, uv_fs_cb cb);
+    uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
 
 
 enum uv_fs_event {
@@ -1805,8 +1840,6 @@ UV_EXTERN extern uint64_t uv_hrtime(void);
  * Note that this function works on a best-effort basis: there is no guarantee
  * that libuv can discover all file descriptors that were inherited. In general
  * it does a better job on Windows than it does on unix.
- *
- * TODO(bb): insert snarky remark to annoy bnoordhuis and the folks at joyent.
  */
 UV_EXTERN void uv_disable_stdio_inheritance(void);
 
diff --git a/src/libuv/src/inet.c b/src/libuv/src/inet.c
index 939a9fa5..8f9d89b0 100644
--- a/src/libuv/src/inet.c
+++ b/src/libuv/src/inet.c
@@ -54,14 +54,14 @@ uv_err_t uv_inet_ntop(int af, const void* src, char* dst, size_t size) {
 static uv_err_t inet_ntop4(const unsigned char *src, char *dst, size_t size) {
   static const char fmt[] = "%u.%u.%u.%u";
   char tmp[sizeof "255.255.255.255"];
-  size_t l;
+  int l;
 
 #ifndef _WIN32
   l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
 #else
   l = _snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
 #endif
-  if (l <= 0 || l >= size) {
+  if (l <= 0 || (size_t) l >= size) {
     return uv_enospc_;
   }
   strncpy(dst, tmp, size);
diff --git a/src/libuv/src/unix/aix.c b/src/libuv/src/unix/aix.c
index 5ea33bbc..8ac6eca0 100644
--- a/src/libuv/src/unix/aix.c
+++ b/src/libuv/src/unix/aix.c
@@ -62,7 +62,6 @@ uint64_t uv__hrtime(void) {
 int uv_exepath(char* buffer, size_t* size) {
   ssize_t res;
   char pp[64], cwdl[PATH_MAX];
-  size_t cwdl_len;
   struct psinfo ps;
   int fd;
 
@@ -79,7 +78,6 @@ int uv_exepath(char* buffer, size_t* size) {
     return res;
 
   cwdl[res] = '\0';
-  cwdl_len = res;
 
   (void) snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid());
   fd = open(pp, O_RDONLY);
diff --git a/src/libuv/src/unix/core.c b/src/libuv/src/unix/core.c
index 9b471ec7..e8e5f9e6 100644
--- a/src/libuv/src/unix/core.c
+++ b/src/libuv/src/unix/core.c
@@ -71,10 +71,8 @@ STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->base) ==
               sizeof(((struct iovec*) 0)->iov_base));
 STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->len) ==
               sizeof(((struct iovec*) 0)->iov_len));
-STATIC_ASSERT((uintptr_t) &((uv_buf_t*) 0)->base ==
-              (uintptr_t) &((struct iovec*) 0)->iov_base);
-STATIC_ASSERT((uintptr_t) &((uv_buf_t*) 0)->len ==
-              (uintptr_t) &((struct iovec*) 0)->iov_len);
+STATIC_ASSERT(offsetof(uv_buf_t, base) == offsetof(struct iovec, iov_base));
+STATIC_ASSERT(offsetof(uv_buf_t, len) == offsetof(struct iovec, iov_len));
 
 
 uint64_t uv_hrtime(void) {
@@ -164,7 +162,12 @@ void uv__make_close_pending(uv_handle_t* handle) {
 
 
 static void uv__finish_close(uv_handle_t* handle) {
-  assert(!uv__is_active(handle));
+  /* Note: while the handle is in the UV_CLOSING state now, it's still possible
+   * for it to be active in the sense that uv__is_active() returns true.
+   * A good example is when the user calls uv_shutdown(), immediately followed
+   * by uv_close(). The handle is considered active at this point because the
+   * completion of the shutdown req is still pending.
+   */
   assert(handle->flags & UV_CLOSING);
   assert(!(handle->flags & UV_CLOSED));
   handle->flags |= UV_CLOSED;
@@ -222,7 +225,7 @@ static void uv__run_closing_handles(uv_loop_t* loop) {
 
 
 int uv_is_closing(const uv_handle_t* handle) {
-  return handle->flags & (UV_CLOSING | UV_CLOSED);
+  return uv__is_closing(handle);
 }
 
 
@@ -299,6 +302,8 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
 
   r = uv__loop_alive(loop);
   while (r != 0 && loop->stop_flag == 0) {
+    UV_TICK_START(loop, mode);
+
     uv__update_time(loop);
     uv__run_timers(loop);
     uv__run_idle(loop);
@@ -314,6 +319,8 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
     uv__run_closing_handles(loop);
     r = uv__loop_alive(loop);
 
+    UV_TICK_STOP(loop, mode);
+
     if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))
       break;
   }
@@ -333,11 +340,6 @@ void uv_update_time(uv_loop_t* loop) {
 }
 
 
-uint64_t uv_now(uv_loop_t* loop) {
-  return loop->time;
-}
-
-
 int uv_is_active(const uv_handle_t* handle) {
   return uv__is_active(handle);
 }
diff --git a/src/libuv/src/unix/cygwin.c b/src/libuv/src/unix/cygwin.c
index 97464541..dcd9d6dd 100644
--- a/src/libuv/src/unix/cygwin.c
+++ b/src/libuv/src/unix/cygwin.c
@@ -55,11 +55,6 @@ void uv_loadavg(double avg[3]) {
 
 
 int uv_exepath(char* buffer, size_t* size) {
-  uint32_t usize;
-  int result;
-  char* path;
-  char* fullpath;
-
   if (!buffer || !size) {
     return -1;
   }
diff --git a/src/libuv/src/unix/darwin-proctitle.m b/src/libuv/src/unix/darwin-proctitle.c
similarity index 89%
rename from src/libuv/src/unix/darwin-proctitle.m
rename to src/libuv/src/unix/darwin-proctitle.c
index d0ee95b4..c3171a61 100644
--- a/src/libuv/src/unix/darwin-proctitle.m
+++ b/src/libuv/src/unix/darwin-proctitle.c
@@ -18,10 +18,18 @@
  * IN THE SOFTWARE.
  */
 
-#include <Cocoa/Cocoa.h>
+#include <TargetConditionals.h>
+
+#if !TARGET_OS_IPHONE
+# include <CoreFoundation/CoreFoundation.h>
+# include <ApplicationServices/ApplicationServices.h>
+#endif
 
 
 int uv__set_process_title(const char* title) {
+#if TARGET_OS_IPHONE
+  return -1;
+#else
   typedef CFTypeRef (*LSGetCurrentApplicationASNType)(void);
   typedef OSStatus (*LSSetApplicationInformationItemType)(int,
                                                           CFTypeRef,
@@ -43,14 +51,14 @@ typedef OSStatus (*LSSetApplicationInformationItemType)(int,
   if (launch_services_bundle == NULL)
     return -1;
 
-  ls_get_current_application_asn =
+  ls_get_current_application_asn = (LSGetCurrentApplicationASNType)
       CFBundleGetFunctionPointerForName(launch_services_bundle,
                                         CFSTR("_LSGetCurrentApplicationASN"));
 
   if (ls_get_current_application_asn == NULL)
     return -1;
 
-  ls_set_application_information_item =
+  ls_set_application_information_item = (LSSetApplicationInformationItemType)
       CFBundleGetFunctionPointerForName(launch_services_bundle,
                                         CFSTR("_LSSetApplicationInformationItem"));
 
@@ -75,4 +83,5 @@ typedef OSStatus (*LSSetApplicationInformationItemType)(int,
                                             NULL);
 
   return (err == noErr) ? 0 : -1;
+#endif  /* !TARGET_OS_IPHONE */
 }
diff --git a/src/libuv/src/unix/darwin.c b/src/libuv/src/unix/darwin.c
index cfbfed23..77e662f4 100644
--- a/src/libuv/src/unix/darwin.c
+++ b/src/libuv/src/unix/darwin.c
@@ -38,8 +38,8 @@
 #include <unistd.h>  /* sysconf */
 
 /* Forward declarations */
-void uv__cf_loop_runner(void* arg);
-void uv__cf_loop_cb(void* arg);
+static void uv__cf_loop_runner(void* arg);
+static void uv__cf_loop_cb(void* arg);
 
 typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t;
 struct uv__cf_loop_signal_s {
@@ -84,9 +84,8 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
   uv__cf_loop_signal_t* s;
 
   assert(loop->cf_loop != NULL);
-  CFRunLoopStop(loop->cf_loop);
+  uv__cf_loop_signal(loop, NULL, NULL);
   uv_thread_join(&loop->cf_thread);
-  loop->cf_loop = NULL;
 
   uv_sem_destroy(&loop->cf_sem);
   uv_mutex_destroy(&loop->cf_mutex);
@@ -103,7 +102,7 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
 }
 
 
-void uv__cf_loop_runner(void* arg) {
+static void uv__cf_loop_runner(void* arg) {
   uv_loop_t* loop;
 
   loop = arg;
@@ -125,7 +124,7 @@ void uv__cf_loop_runner(void* arg) {
 }
 
 
-void uv__cf_loop_cb(void* arg) {
+static void uv__cf_loop_cb(void* arg) {
   uv_loop_t* loop;
   ngx_queue_t* item;
   ngx_queue_t split_head;
@@ -145,7 +144,12 @@ void uv__cf_loop_cb(void* arg) {
     item = ngx_queue_head(&split_head);
 
     s = ngx_queue_data(item, uv__cf_loop_signal_t, member);
-    s->cb(s->arg);
+
+    /* This was a termination signal */
+    if (s->cb == NULL)
+      CFRunLoopStop(loop->cf_loop);
+    else
+      s->cb(s->arg);
 
     ngx_queue_remove(item);
     free(s);
@@ -253,19 +257,21 @@ void uv_loadavg(double avg[3]) {
 
 
 uv_err_t uv_resident_set_memory(size_t* rss) {
-  struct task_basic_info t_info;
-  mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
-
-  int r = task_info(mach_task_self(),
-                    TASK_BASIC_INFO,
-                    (task_info_t)&t_info,
-                    &t_info_count);
-
-  if (r != KERN_SUCCESS) {
-    return uv__new_sys_error(errno);
-  }
-
-  *rss = t_info.resident_size;
+  mach_msg_type_number_t count;
+  task_basic_info_data_t info;
+  kern_return_t err;
+
+  count = TASK_BASIC_INFO_COUNT;
+  err = task_info(mach_task_self(),
+                  TASK_BASIC_INFO,
+                  (task_info_t) &info,
+                  &count);
+  (void) &err;
+  /* task_info(TASK_BASIC_INFO) cannot really fail. Anything other than
+   * KERN_SUCCESS implies a libuv bug.
+   */
+  assert(err == KERN_SUCCESS);
+  *rss = info.resident_size;
 
   return uv_ok_;
 }
diff --git a/src/libuv/src/unix/error.c b/src/libuv/src/unix/error.c
index 9e3e84ad..05ab4820 100644
--- a/src/libuv/src/unix/error.c
+++ b/src/libuv/src/unix/error.c
@@ -79,6 +79,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
     case EMSGSIZE: return UV_EMSGSIZE;
     case ENAMETOOLONG: return UV_ENAMETOOLONG;
     case EINVAL: return UV_EINVAL;
+    case ENETDOWN: return UV_ENETDOWN;
     case ENETUNREACH: return UV_ENETUNREACH;
     case ECONNABORTED: return UV_ECONNABORTED;
     case ELOOP: return UV_ELOOP;
diff --git a/src/libuv/src/unix/fs.c b/src/libuv/src/unix/fs.c
index 53f46ce7..dde1d3a8 100644
--- a/src/libuv/src/unix/fs.c
+++ b/src/libuv/src/unix/fs.c
@@ -436,11 +436,14 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
      * non-blocking mode and not all data could be written. If a non-zero
      * number of bytes have been sent, we don't consider it an error.
      */
-    len = 0;
 
 #if defined(__FreeBSD__)
+    len = 0;
     r = sendfile(in_fd, out_fd, req->off, req->len, NULL, &len, 0);
 #else
+    /* The darwin sendfile takes len as an input for the length to send,
+     * so make sure to initialize it with the caller's value. */
+    len = req->len;
     r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
 #endif
 
@@ -595,8 +598,8 @@ int uv_fs_chmod(uv_loop_t* loop,
 int uv_fs_chown(uv_loop_t* loop,
                 uv_fs_t* req,
                 const char* path,
-                int uid,
-                int gid,
+                uv_uid_t uid,
+                uv_gid_t gid,
                 uv_fs_cb cb) {
   INIT(CHOWN);
   PATH;
@@ -628,8 +631,8 @@ int uv_fs_fchmod(uv_loop_t* loop,
 int uv_fs_fchown(uv_loop_t* loop,
                  uv_fs_t* req,
                  uv_file file,
-                 int uid,
-                 int gid,
+                 uv_uid_t uid,
+                 uv_gid_t gid,
                  uv_fs_cb cb) {
   INIT(FCHOWN);
   req->file = file;
diff --git a/src/libuv/src/unix/internal.h b/src/libuv/src/unix/internal.h
index 35b3b8ca..61cb1ec1 100644
--- a/src/libuv/src/unix/internal.h
+++ b/src/libuv/src/unix/internal.h
@@ -46,7 +46,7 @@
 #endif
 
 #define STATIC_ASSERT(expr)                                                   \
-  void uv__static_assert(int static_assert_failed[0 - !(expr)])
+  void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)])
 
 #define ACCESS_ONCE(type, var)                                                \
   (*(volatile type*) &(var))
@@ -148,6 +148,9 @@ void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream,
     uv_handle_type type);
 int uv__stream_open(uv_stream_t*, int fd, int flags);
 void uv__stream_destroy(uv_stream_t* stream);
+#if defined(__APPLE__)
+int uv__stream_try_select(uv_stream_t* stream, int* fd);
+#endif /* defined(__APPLE__) */
 void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
 int uv__accept(int sockfd);
 
@@ -253,4 +256,11 @@ static void uv__update_time(uv_loop_t* loop) {
   loop->time = uv__hrtime() / 1000000;
 }
 
+#ifdef HAVE_DTRACE
+#include "uv-dtrace.h"
+#else
+#define UV_TICK_START(arg0, arg1)
+#define UV_TICK_STOP(arg0, arg1)
+#endif
+
 #endif /* UV_UNIX_INTERNAL_H_ */
diff --git a/src/libuv/src/unix/linux-core.c b/src/libuv/src/unix/linux-core.c
index daab6f19..e4c34a18 100644
--- a/src/libuv/src/unix/linux-core.c
+++ b/src/libuv/src/unix/linux-core.c
@@ -284,98 +284,59 @@ uint64_t uv_get_total_memory(void) {
 
 
 uv_err_t uv_resident_set_memory(size_t* rss) {
-  FILE* f;
-  int itmp;
-  char ctmp;
-  unsigned int utmp;
-  size_t page_size = getpagesize();
-  char *cbuf;
-  int foundExeEnd;
-  char buf[PATH_MAX + 1];
-
-  f = fopen("/proc/self/stat", "r");
-  if (!f) return uv__new_sys_error(errno);
-
-  /* PID */
-  if (fscanf(f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Exec file */
-  cbuf = buf;
-  foundExeEnd = 0;
-  if (fscanf (f, "%c", cbuf++) == 0) goto error;
-  while (1) {
-    if (fscanf(f, "%c", cbuf) == 0) goto error;
-    if (*cbuf == ')') {
-      foundExeEnd = 1;
-    } else if (foundExeEnd && *cbuf == ' ') {
-      *cbuf = 0;
-      break;
-    }
+  char buf[1024];
+  const char* s;
+  ssize_t n;
+  long val;
+  int fd;
+  int i;
 
-    cbuf++;
+  do
+    fd = open("/proc/self/stat", O_RDONLY);
+  while (fd == -1 && errno == EINTR);
+
+  if (fd == -1)
+    return uv__new_sys_error(errno);
+
+  do
+    n = read(fd, buf, sizeof(buf) - 1);
+  while (n == -1 && errno == EINTR);
+
+  SAVE_ERRNO(close(fd));
+  if (n == -1)
+    return uv__new_sys_error(errno);
+  buf[n] = '\0';
+
+  s = strchr(buf, ' ');
+  if (s == NULL)
+    goto err;
+
+  s += 1;
+  if (*s != '(')
+    goto err;
+
+  s = strchr(s, ')');
+  if (s == NULL)
+    goto err;
+
+  for (i = 1; i <= 22; i++) {
+    s = strchr(s + 1, ' ');
+    if (s == NULL)
+      goto err;
   }
-  /* State */
-  if (fscanf (f, "%c ", &ctmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Parent process */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Process group */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Session id */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* TTY */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* TTY owner process group */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Flags */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Minor faults (no memory page) */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Minor faults, children */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Major faults (memory page faults) */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Major faults, children */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  /* utime */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* stime */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* utime, children */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* stime, children */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* jiffies remaining in current time slice */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* 'nice' value */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-  /* jiffies until next timeout */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  /* jiffies until next SIGALRM */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  /* start time (jiffies since system boot) */
-  if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
-
-  /* Virtual memory size */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-
-  /* Resident set size */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  *rss = (size_t) utmp * page_size;
-
-  /* rlim */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Start of text */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  /* End of text */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-  /* Start of stack */
-  if (fscanf (f, "%u ", &utmp) == 0) goto error; /* coverity[secure_coding] */
-
-  fclose (f);
+
+  errno = 0;
+  val = strtol(s, NULL, 10);
+  if (errno != 0)
+    goto err;
+  if (val < 0)
+    goto err;
+
+  *rss = val * getpagesize();
   return uv_ok_;
 
-error:
-  fclose (f);
-  return uv__new_sys_error(errno);
+err:
+  return uv__new_artificial_error(UV_EINVAL);
 }
 
 
@@ -421,12 +382,12 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
     return uv__new_sys_error(ENOMEM);
 
   if (read_models(numcpus, ci)) {
-    SAVE_ERRNO(free(ci));
+    SAVE_ERRNO(uv_free_cpu_info(ci, numcpus));
     return uv__new_sys_error(errno);
   }
 
   if (read_times(numcpus, ci)) {
-    SAVE_ERRNO(free(ci));
+    SAVE_ERRNO(uv_free_cpu_info(ci, numcpus));
     return uv__new_sys_error(errno);
   }
 
@@ -453,76 +414,96 @@ static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci) {
 
 /* Also reads the CPU frequency on x86. The other architectures only have
  * a BogoMIPS field, which may not be very accurate.
+ *
+ * Note: Simply returns on error, uv_cpu_info() takes care of the cleanup.
  */
 static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
-#if defined(__i386__) || defined(__x86_64__)
   static const char model_marker[] = "model name\t: ";
   static const char speed_marker[] = "cpu MHz\t\t: ";
-#elif defined(__arm__)
-  static const char model_marker[] = "Processor\t: ";
-  static const char speed_marker[] = "";
-#elif defined(__mips__)
-  static const char model_marker[] = "cpu model\t\t: ";
-  static const char speed_marker[] = "";
-#else
-# warning uv_cpu_info() is not supported on this architecture.
-  static const char model_marker[] = "";
-  static const char speed_marker[] = "";
-#endif
-  static const char bogus_model[] = "unknown";
+  const char* inferred_model;
   unsigned int model_idx;
   unsigned int speed_idx;
   char buf[1024];
   char* model;
   FILE* fp;
-  char* inferred_model;
 
-  fp = fopen("/proc/cpuinfo", "r");
-  if (fp == NULL)
-    return -1;
+  /* Most are unused on non-ARM, non-MIPS and non-x86 architectures. */
+  (void) &model_marker;
+  (void) &speed_marker;
+  (void) &speed_idx;
+  (void) &model;
+  (void) &buf;
+  (void) &fp;
 
   model_idx = 0;
   speed_idx = 0;
 
+#if defined(__arm__) || \
+    defined(__i386__) || \
+    defined(__mips__) || \
+    defined(__x86_64__)
+  fp = fopen("/proc/cpuinfo", "r");
+  if (fp == NULL)
+    return -1;
+
   while (fgets(buf, sizeof(buf), fp)) {
-    if (model_marker[0] != '\0' &&
-        model_idx < numcpus &&
-        strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0)
-    {
-      model = buf + sizeof(model_marker) - 1;
-      model = strndup(model, strlen(model) - 1); /* strip newline */
-      ci[model_idx++].model = model;
-      continue;
+    if (model_idx < numcpus) {
+      if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) {
+        model = buf + sizeof(model_marker) - 1;
+        model = strndup(model, strlen(model) - 1);  /* Strip newline. */
+        if (model == NULL) {
+          fclose(fp);
+          return -1;
+        }
+        ci[model_idx++].model = model;
+        continue;
+      }
     }
-
-    if (speed_marker[0] != '\0' &&
-        speed_idx < numcpus &&
-        strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0)
-    {
-      ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1);
-      continue;
+#if defined(__arm__) || defined(__mips__)
+    if (model_idx < numcpus) {
+#if defined(__arm__)
+      /* Fallback for pre-3.8 kernels. */
+      static const char model_marker[] = "Processor\t: ";
+#else	/* defined(__mips__) */
+      static const char model_marker[] = "cpu model\t\t: ";
+#endif
+      if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) {
+        model = buf + sizeof(model_marker) - 1;
+        model = strndup(model, strlen(model) - 1);  /* Strip newline. */
+        if (model == NULL) {
+          fclose(fp);
+          return -1;
+        }
+        ci[model_idx++].model = model;
+        continue;
+      }
     }
+#else  /* !__arm__ && !__mips__ */
+    if (speed_idx < numcpus) {
+      if (strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0) {
+        ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1);
+        continue;
+      }
+    }
+#endif  /* __arm__ || __mips__ */
   }
-  fclose(fp);
 
-  /* Now we want to make sure that all the models contain *something*:
-   * it's not safe to leave them as null.
-   */
-  if (model_idx == 0) {
-    /* No models at all: fake up the first one. */
-    ci[0].model = strndup(bogus_model, sizeof(bogus_model) - 1);
-    model_idx = 1;
-  }
+  fclose(fp);
+#endif  /* __arm__ || __i386__ || __mips__ || __x86_64__ */
 
-  /* Not enough models, but we do have at least one.  So we'll just
-   * copy the rest down: it might be better to indicate somehow that
-   * the remaining ones have been guessed.
+  /* Now we want to make sure that all the models contain *something* because
+   * it's not safe to leave them as null. Copy the last entry unless there
+   * isn't one, in that case we simply put "unknown" into everything.
    */
-  inferred_model = ci[model_idx - 1].model;
+  inferred_model = "unknown";
+  if (model_idx > 0)
+    inferred_model = ci[model_idx - 1].model;
 
   while (model_idx < numcpus) {
-    ci[model_idx].model = strndup(inferred_model, strlen(inferred_model));
-    model_idx++;
+    model = strndup(inferred_model, strlen(inferred_model));
+    if (model == NULL)
+      return -1;
+    ci[model_idx++].model = model;
   }
 
   return 0;
diff --git a/src/libuv/src/unix/pipe.c b/src/libuv/src/unix/pipe.c
index 1185b91a..4b7f966b 100644
--- a/src/libuv/src/unix/pipe.c
+++ b/src/libuv/src/unix/pipe.c
@@ -155,6 +155,11 @@ void uv__pipe_close(uv_pipe_t* handle) {
 
 
 int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
+#if defined(__APPLE__)
+  if (uv__stream_try_select((uv_stream_t*) handle, &fd))
+    return -1;
+#endif /* defined(__APPLE__) */
+
   return uv__stream_open((uv_stream_t*)handle,
                          fd,
                          UV_STREAM_READABLE | UV_STREAM_WRITABLE);
diff --git a/src/libuv/src/unix/signal.c b/src/libuv/src/unix/signal.c
index f7fd2e5e..22c7783b 100644
--- a/src/libuv/src/unix/signal.c
+++ b/src/libuv/src/unix/signal.c
@@ -160,7 +160,7 @@ static void uv__signal_handler(int signum) {
     } while (r == -1 && errno == EINTR);
 
     assert(r == sizeof msg ||
-           (r == -1 && errno != EAGAIN && errno != EWOULDBLOCK));
+           (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)));
 
     if (r != -1)
       handle->caught_signals++;
diff --git a/src/libuv/src/unix/stream.c b/src/libuv/src/unix/stream.c
index 8137d24e..c9df9797 100644
--- a/src/libuv/src/unix/stream.c
+++ b/src/libuv/src/unix/stream.c
@@ -33,6 +33,7 @@
 #include <sys/uio.h>
 #include <sys/un.h>
 #include <unistd.h>
+#include <limits.h> /* IOV_MAX */
 
 #if defined(__APPLE__)
 # include <sys/event.h>
@@ -45,8 +46,8 @@ typedef struct uv__stream_select_s uv__stream_select_t;
 struct uv__stream_select_s {
   uv_stream_t* stream;
   uv_thread_t thread;
-  uv_sem_t sem;
-  uv_mutex_t mutex;
+  uv_sem_t close_sem;
+  uv_sem_t async_sem;
   uv_async_t async;
   int events;
   int fake_fd;
@@ -59,6 +60,7 @@ static void uv__stream_connect(uv_stream_t*);
 static void uv__write(uv_stream_t* stream);
 static void uv__read(uv_stream_t* stream);
 static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
+static size_t uv__write_req_size(uv_write_t* req);
 
 
 /* Used by the accept() EMFILE party trick. */
@@ -131,7 +133,6 @@ static void uv__stream_osx_select(void* arg) {
   char buf[1024];
   fd_set sread;
   fd_set swrite;
-  fd_set serror;
   int events;
   int fd;
   int r;
@@ -139,7 +140,7 @@ static void uv__stream_osx_select(void* arg) {
 
   stream = arg;
   s = stream->select;
-  fd = stream->io_watcher.fd;
+  fd = s->fd;
 
   if (fd > s->int_fd)
     max_fd = fd;
@@ -148,23 +149,21 @@ static void uv__stream_osx_select(void* arg) {
 
   while (1) {
     /* Terminate on semaphore */
-    if (uv_sem_trywait(&s->sem) == 0)
+    if (uv_sem_trywait(&s->close_sem) == 0)
       break;
 
     /* Watch fd using select(2) */
     FD_ZERO(&sread);
     FD_ZERO(&swrite);
-    FD_ZERO(&serror);
 
     if (uv_is_readable(stream))
       FD_SET(fd, &sread);
     if (uv_is_writable(stream))
       FD_SET(fd, &swrite);
-    FD_SET(fd, &serror);
     FD_SET(s->int_fd, &sread);
 
     /* Wait indefinitely for fd events */
-    r = select(max_fd + 1, &sread, &swrite, &serror, NULL);
+    r = select(max_fd + 1, &sread, &swrite, NULL, NULL);
     if (r == -1) {
       if (errno == EINTR)
         continue;
@@ -203,15 +202,17 @@ static void uv__stream_osx_select(void* arg) {
       events |= UV__POLLIN;
     if (FD_ISSET(fd, &swrite))
       events |= UV__POLLOUT;
-    if (FD_ISSET(fd, &serror))
-      events |= UV__POLLERR;
 
-    uv_mutex_lock(&s->mutex);
-    s->events |= events;
-    uv_mutex_unlock(&s->mutex);
+    assert(events != 0 || FD_ISSET(s->int_fd, &sread));
+    if (events != 0) {
+      ACCESS_ONCE(int, s->events) = events;
 
-    if (events != 0)
       uv_async_send(&s->async);
+      uv_sem_wait(&s->async_sem);
+
+      /* Should be processed at this stage */
+      assert((s->events == 0) || (stream->flags & UV_CLOSING));
+    }
   }
 }
 
@@ -244,12 +245,12 @@ static void uv__stream_osx_select_cb(uv_async_t* handle, int status) {
   stream = s->stream;
 
   /* Get and reset stream's events */
-  uv_mutex_lock(&s->mutex);
   events = s->events;
-  s->events = 0;
-  uv_mutex_unlock(&s->mutex);
+  ACCESS_ONCE(int, s->events) = 0;
+  uv_sem_post(&s->async_sem);
 
-  assert(0 == (events & UV__POLLERR));
+  assert(events != 0);
+  assert(events == (events & (UV__POLLIN | UV__POLLOUT)));
 
   /* Invoke callback on event-loop */
   if ((events & UV__POLLIN) && uv__io_active(&stream->io_watcher, UV__POLLIN))
@@ -268,7 +269,7 @@ static void uv__stream_osx_cb_close(uv_handle_t* async) {
 }
 
 
-static int uv__stream_try_select(uv_stream_t* stream, int fd) {
+int uv__stream_try_select(uv_stream_t* stream, int* fd) {
   /*
    * kqueue doesn't work with some files from /dev mount on osx.
    * select(2) in separate thread for those fds
@@ -288,7 +289,7 @@ static int uv__stream_try_select(uv_stream_t* stream, int fd) {
     return uv__set_sys_error(stream->loop, errno);
   }
 
-  EV_SET(&filter[0], fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
+  EV_SET(&filter[0], *fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
 
   /* Use small timeout, because we only want to capture EINVALs */
   timeout.tv_sec = 0;
@@ -308,7 +309,8 @@ static int uv__stream_try_select(uv_stream_t* stream, int fd) {
   if (s == NULL)
     return uv__set_artificial_error(stream->loop, UV_ENOMEM);
 
-  s->fd = fd;
+  s->events = 0;
+  s->fd = *fd;
 
   if (uv_async_init(stream->loop, &s->async, uv__stream_osx_select_cb)) {
     SAVE_ERRNO(free(s));
@@ -318,10 +320,10 @@ static int uv__stream_try_select(uv_stream_t* stream, int fd) {
   s->async.flags |= UV__HANDLE_INTERNAL;
   uv__handle_unref(&s->async);
 
-  if (uv_sem_init(&s->sem, 0))
+  if (uv_sem_init(&s->close_sem, 0))
     goto fatal1;
 
-  if (uv_mutex_init(&s->mutex))
+  if (uv_sem_init(&s->async_sem, 0))
     goto fatal2;
 
   /* Create fds for io watcher and to interrupt the select() loop. */
@@ -336,6 +338,7 @@ static int uv__stream_try_select(uv_stream_t* stream, int fd) {
 
   s->stream = stream;
   stream->select = s;
+  *fd = s->fake_fd;
 
   return 0;
 
@@ -345,9 +348,9 @@ static int uv__stream_try_select(uv_stream_t* stream, int fd) {
   s->fake_fd = -1;
   s->int_fd = -1;
 fatal3:
-  uv_mutex_destroy(&s->mutex);
+  uv_sem_destroy(&s->async_sem);
 fatal2:
-  uv_sem_destroy(&s->sem);
+  uv_sem_destroy(&s->close_sem);
 fatal1:
   uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close);
   return uv__set_sys_error(stream->loop, errno);
@@ -368,21 +371,6 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
       return uv__set_sys_error(stream->loop, errno);
   }
 
-#if defined(__APPLE__)
-  {
-    uv__stream_select_t* s;
-    int r;
-
-    r = uv__stream_try_select(stream, fd);
-    if (r == -1)
-      return r;
-
-    s = stream->select;
-    if (s != NULL)
-      fd = s->fake_fd;
-  }
-#endif /* defined(__APPLE__) */
-
   stream->io_watcher.fd = fd;
 
   return 0;
@@ -412,6 +400,7 @@ void uv__stream_destroy(uv_stream_t* stream) {
 
     if (req->bufs != req->bufsml)
       free(req->bufs);
+    req->bufs = NULL;
 
     if (req->cb) {
       uv__set_artificial_error(req->handle->loop, UV_ECANCELED);
@@ -426,6 +415,13 @@ void uv__stream_destroy(uv_stream_t* stream) {
     req = ngx_queue_data(q, uv_write_t, queue);
     uv__req_unregister(stream->loop, req);
 
+    if (req->bufs != NULL) {
+      stream->write_queue_size -= uv__write_req_size(req);
+      if (req->bufs != req->bufsml)
+        free(req->bufs);
+      req->bufs = NULL;
+    }
+
     if (req->cb) {
       uv__set_sys_error(stream->loop, req->error);
       req->cb(req, req->error ? -1 : 0);
@@ -433,6 +429,11 @@ void uv__stream_destroy(uv_stream_t* stream) {
   }
 
   if (stream->shutdown_req) {
+    /* The UV_ECANCELED error code is a lie, the shutdown(2) syscall is a
+     * fait accompli at this point. Maybe we should revisit this in v0.11.
+     * A possible reason for leaving it unchanged is that it informs the
+     * callee that the handle has been destroyed.
+     */
     uv__req_unregister(stream->loop, stream->shutdown_req);
     uv__set_artificial_error(stream->loop, UV_ECANCELED);
     stream->shutdown_req->cb(stream->shutdown_req, -1);
@@ -454,7 +455,6 @@ void uv__stream_destroy(uv_stream_t* stream) {
  */
 static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
   int fd;
-  int r;
 
   if (loop->emfile_fd == -1)
     return -1;
@@ -472,14 +472,8 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
     if (errno == EINTR)
       continue;
 
-    if (errno == EAGAIN || errno == EWOULDBLOCK)
-      r = 0;
-    else
-      r = -1;
-
-    loop->emfile_fd = uv__open_cloexec("/", O_RDONLY);
-
-    return r;
+    SAVE_ERRNO(loop->emfile_fd = uv__open_cloexec("/", O_RDONLY));
+    return errno;
   }
 }
 
@@ -492,10 +486,9 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
 
 
 void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
-  static int use_emfile_trick = -1;
   uv_stream_t* stream;
+  int err;
   int fd;
-  int r;
 
   stream = container_of(w, uv_stream_t, io_watcher);
   assert(events == UV__POLLIN);
@@ -510,50 +503,32 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
    */
   while (uv__stream_fd(stream) != -1) {
     assert(stream->accepted_fd == -1);
+
 #if defined(UV_HAVE_KQUEUE)
     if (w->rcount <= 0)
       return;
 #endif /* defined(UV_HAVE_KQUEUE) */
-    fd = uv__accept(uv__stream_fd(stream));
 
+    fd = uv__accept(uv__stream_fd(stream));
     if (fd == -1) {
-      switch (errno) {
-#if EWOULDBLOCK != EAGAIN
-      case EWOULDBLOCK:
-#endif
-      case EAGAIN:
-        return; /* Not an error. */
-
-      case ECONNABORTED:
-        UV_DEC_BACKLOG(w)
-        continue; /* Ignore. */
-
-      case EMFILE:
-      case ENFILE:
-        if (use_emfile_trick == -1) {
-          const char* val = getenv("UV_ACCEPT_EMFILE_TRICK");
-          use_emfile_trick = (val == NULL || atoi(val) != 0);
-        }
+      if (errno == EAGAIN || errno == EWOULDBLOCK)
+        return;  /* Not an error. */
 
-        if (use_emfile_trick) {
-          SAVE_ERRNO(r = uv__emfile_trick(loop, uv__stream_fd(stream)));
-          if (r == 0) {
-            UV_DEC_BACKLOG(w)
-            continue;
-          }
-        }
-
-        /* Fall through. */
+      if (errno == ECONNABORTED)
+        continue;  /* Ignore. Nothing we can do about that. */
 
-      default:
-        uv__set_sys_error(loop, errno);
-        stream->connection_cb(stream, -1);
-        continue;
+      if (errno == EMFILE || errno == ENFILE) {
+        SAVE_ERRNO(err = uv__emfile_trick(loop, uv__stream_fd(stream)));
+        if (err == EAGAIN || err == EWOULDBLOCK)
+          break;
       }
+
+      uv__set_sys_error(loop, errno);
+      stream->connection_cb(stream, -1);
+      continue;
     }
 
     UV_DEC_BACKLOG(w)
-
     stream->accepted_fd = fd;
     stream->connection_cb(stream, 0);
 
@@ -655,10 +630,9 @@ 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));
-  assert(stream->write_queue_size == 0);
-
   uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
 
   /* Shutdown? */
@@ -669,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);
   }
 }
 
@@ -691,6 +661,7 @@ static void uv__drain(uv_stream_t* stream) {
 static size_t uv__write_req_size(uv_write_t* req) {
   size_t size;
 
+  assert(req->bufs != NULL);
   size = uv__buf_count(req->bufs + req->write_index,
                        req->bufcnt - req->write_index);
   assert(req->handle->write_queue_size >= size);
@@ -704,10 +675,18 @@ static void uv__write_req_finish(uv_write_t* req) {
 
   /* Pop the req off tcp->write_queue. */
   ngx_queue_remove(&req->queue);
-  if (req->bufs != req->bufsml) {
-    free(req->bufs);
+
+  /* Only free when there was no error. On error, we touch up write_queue_size
+   * right before making the callback. The reason we don't do that right away
+   * is that a write_queue_size > 0 is our only way to signal to the user that
+   * he should stop writing - which he should if we got an error. Something to
+   * revisit in future revisions of the libuv API.
+   */
+  if (req->error == 0) {
+    if (req->bufs != req->bufsml)
+      free(req->bufs);
+    req->bufs = NULL;
   }
-  req->bufs = NULL;
 
   /* Add it to the write_completed_queue where it will have its
    * callback called in the near future.
@@ -743,10 +722,8 @@ static void uv__write(uv_stream_t* stream) {
 
   assert(uv__stream_fd(stream) >= 0);
 
-  if (ngx_queue_empty(&stream->write_queue)) {
-    assert(stream->write_queue_size == 0);
+  if (ngx_queue_empty(&stream->write_queue))
     return;
-  }
 
   q = ngx_queue_head(&stream->write_queue);
   req = ngx_queue_data(q, uv_write_t, queue);
@@ -760,6 +737,10 @@ static void uv__write(uv_stream_t* stream) {
   iov = (struct iovec*) &(req->bufs[req->write_index]);
   iovcnt = req->bufcnt - req->write_index;
 
+  /* Limit iov count to avoid EINVALs from writev() */
+  if (iovcnt > IOV_MAX)
+    iovcnt = IOV_MAX;
+
   /*
    * Now do the actual writev. Note that we've been updating the pointers
    * inside the iov each time we write. So there is no need to offset it.
@@ -813,8 +794,10 @@ static void uv__write(uv_stream_t* stream) {
     if (errno != EAGAIN && errno != EWOULDBLOCK) {
       /* Error */
       req->error = errno;
-      stream->write_queue_size -= uv__write_req_size(req);
       uv__write_req_finish(req);
+      uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
+      if (!uv__io_active(&stream->io_watcher, UV__POLLIN))
+        uv__handle_stop(stream);
       return;
     } else if (stream->flags & UV_STREAM_BLOCKING) {
       /* If this is a blocking stream, try again. */
@@ -890,6 +873,13 @@ static void uv__write_callbacks(uv_stream_t* stream) {
     ngx_queue_remove(q);
     uv__req_unregister(stream->loop, req);
 
+    if (req->bufs != NULL) {
+      stream->write_queue_size -= uv__write_req_size(req);
+      if (req->bufs != req->bufsml)
+        free(req->bufs);
+      req->bufs = NULL;
+    }
+
     /* NOTE: call callback AFTER freeing the request data. */
     if (req->cb) {
       uv__set_sys_error(stream->loop, req->error);
@@ -1128,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);
@@ -1171,6 +1161,7 @@ static void uv__stream_connect(uv_stream_t* stream) {
 
   stream->connect_req = NULL;
   uv__req_unregister(stream->loop, req);
+  uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
 
   if (req->cb) {
     uv__set_sys_error(stream->loop, error);
@@ -1210,6 +1201,12 @@ int uv_write2(uv_write_t* req,
       return uv__set_artificial_error(stream->loop, UV_EBADF);
   }
 
+  /* It's legal for write_queue_size > 0 even when the write_queue is empty;
+   * it means there are error-state requests in the write_completed_queue that
+   * will touch up write_queue_size later, see also uv__write_req_finish().
+   * We chould check that write_queue is empty instead but that implies making
+   * a write() syscall when we know that the handle is in error mode.
+   */
   empty_queue = (stream->write_queue_size == 0);
 
   /* Initialize the req */
@@ -1318,9 +1315,10 @@ int uv_read2_start(uv_stream_t* stream, uv_alloc_cb alloc_cb,
 
 
 int uv_read_stop(uv_stream_t* stream) {
-  uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
-  uv__handle_stop(stream);
   stream->flags &= ~UV_STREAM_READING;
+  uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
+  if (!uv__io_active(&stream->io_watcher, UV__POLLOUT))
+    uv__handle_stop(stream);
 
 #if defined(__APPLE__)
   /* Notify select() thread about state change */
@@ -1370,11 +1368,12 @@ void uv__stream_close(uv_stream_t* handle) {
 
     s = handle->select;
 
-    uv_sem_post(&s->sem);
+    uv_sem_post(&s->close_sem);
+    uv_sem_post(&s->async_sem);
     uv__stream_osx_interrupt_select(handle);
     uv_thread_join(&s->thread);
-    uv_sem_destroy(&s->sem);
-    uv_mutex_destroy(&s->mutex);
+    uv_sem_destroy(&s->close_sem);
+    uv_sem_destroy(&s->async_sem);
     close(s->fake_fd);
     close(s->int_fd);
     uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close);
@@ -1383,8 +1382,9 @@ void uv__stream_close(uv_stream_t* handle) {
   }
 #endif /* defined(__APPLE__) */
 
-  uv_read_stop(handle);
   uv__io_close(handle->loop, &handle->io_watcher);
+  uv_read_stop(handle);
+  uv__handle_stop(handle);
 
   close(handle->io_watcher.fd);
   handle->io_watcher.fd = -1;
diff --git a/src/libuv/src/unix/tcp.c b/src/libuv/src/unix/tcp.c
index a51576ba..26ab53db 100644
--- a/src/libuv/src/unix/tcp.c
+++ b/src/libuv/src/unix/tcp.c
@@ -343,11 +343,11 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
 }
 
 
-int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int on) {
-  if (on)
-    handle->flags |= UV_TCP_SINGLE_ACCEPT;
-  else
+int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
+  if (enable)
     handle->flags &= ~UV_TCP_SINGLE_ACCEPT;
+  else
+    handle->flags |= UV_TCP_SINGLE_ACCEPT;
   return 0;
 }
 
diff --git a/src/libuv/src/unix/thread.c b/src/libuv/src/unix/thread.c
index e44a77ff..4d59e938 100644
--- a/src/libuv/src/unix/thread.c
+++ b/src/libuv/src/unix/thread.c
@@ -42,7 +42,7 @@ int uv_thread_join(uv_thread_t *tid) {
 
 
 int uv_mutex_init(uv_mutex_t* mutex) {
-#ifdef NDEBUG
+#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
   if (pthread_mutex_init(mutex, NULL))
     return -1;
   else
diff --git a/src/libuv/src/unix/timer.c b/src/libuv/src/unix/timer.c
index 41038c8a..57d32f58 100644
--- a/src/libuv/src/unix/timer.c
+++ b/src/libuv/src/unix/timer.c
@@ -21,6 +21,8 @@
 #include "uv.h"
 #include "internal.h"
 #include <assert.h>
+#include <limits.h>
+
 
 static int uv__timer_cmp(const uv_timer_t* a, const uv_timer_t* b) {
   if (a->timeout < b->timeout)
@@ -45,6 +47,7 @@ RB_GENERATE_STATIC(uv__timers, uv_timer_s, tree_entry, uv__timer_cmp)
 int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
   uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);
   handle->timer_cb = NULL;
+  handle->repeat = 0;
 
   return 0;
 }
@@ -54,11 +57,17 @@ int uv_timer_start(uv_timer_t* handle,
                    uv_timer_cb cb,
                    uint64_t timeout,
                    uint64_t repeat) {
+  uint64_t clamped_timeout;
+
   if (uv__is_active(handle))
     uv_timer_stop(handle);
 
+  clamped_timeout = handle->loop->time + timeout;
+  if (clamped_timeout < timeout)
+    clamped_timeout = (uint64_t) -1;
+
   handle->timer_cb = cb;
-  handle->timeout = handle->loop->time + timeout;
+  handle->timeout = clamped_timeout;
   handle->repeat = repeat;
   /* start_id is the second index to be compared in uv__timer_cmp() */
   handle->start_id = handle->loop->timer_counter++;
@@ -106,6 +115,7 @@ uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
 
 int uv__next_timeout(const uv_loop_t* loop) {
   const uv_timer_t* handle;
+  uint64_t diff;
 
   /* RB_MIN expects a non-const tree root. That's okay, it doesn't modify it. */
   handle = RB_MIN(uv__timers, (struct uv__timers*) &loop->timer_handles);
@@ -116,7 +126,11 @@ int uv__next_timeout(const uv_loop_t* loop) {
   if (handle->timeout <= loop->time)
     return 0;
 
-  return handle->timeout - loop->time;
+  diff = handle->timeout - loop->time;
+  if (diff > INT_MAX)
+    diff = INT_MAX;
+
+  return diff;
 }
 
 
diff --git a/src/libuv/src/unix/tty.c b/src/libuv/src/unix/tty.c
index 49efee7f..a2b76add 100644
--- a/src/libuv/src/unix/tty.c
+++ b/src/libuv/src/unix/tty.c
@@ -36,6 +36,11 @@ static struct termios orig_termios;
 int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
   uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY);
 
+#if defined(__APPLE__)
+  if (uv__stream_try_select((uv_stream_t*) tty, &fd))
+    return -1;
+#endif /* defined(__APPLE__) */
+
   if (readable) {
     uv__nonblock(fd, 1);
     uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_READABLE);
@@ -118,25 +123,52 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
 
 
 uv_handle_type uv_guess_handle(uv_file file) {
+  struct sockaddr sa;
   struct stat s;
+  socklen_t len;
+  int type;
 
-  if (file < 0) {
+  if (file < 0)
     return UV_UNKNOWN_HANDLE;
-  }
 
-  if (isatty(file)) {
+  if (isatty(file))
     return UV_TTY;
-  }
 
-  if (fstat(file, &s)) {
+  if (fstat(file, &s))
     return UV_UNKNOWN_HANDLE;
-  }
 
-  if (!S_ISSOCK(s.st_mode) && !S_ISFIFO(s.st_mode)) {
+  if (S_ISREG(s.st_mode))
     return UV_FILE;
+
+  if (S_ISCHR(s.st_mode))
+    return UV_FILE;  /* XXX UV_NAMED_PIPE? */
+
+  if (S_ISFIFO(s.st_mode))
+    return UV_NAMED_PIPE;
+
+  if (!S_ISSOCK(s.st_mode))
+    return UV_UNKNOWN_HANDLE;
+
+  len = sizeof(type);
+  if (getsockopt(file, SOL_SOCKET, SO_TYPE, &type, &len))
+    return UV_UNKNOWN_HANDLE;
+
+  len = sizeof(sa);
+  if (getsockname(file, &sa, &len))
+    return UV_UNKNOWN_HANDLE;
+
+  if (type == SOCK_DGRAM)
+    if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
+      return UV_UDP;
+
+  if (type == SOCK_STREAM) {
+    if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
+      return UV_TCP;
+    if (sa.sa_family == AF_UNIX)
+      return UV_NAMED_PIPE;
   }
 
-  return UV_NAMED_PIPE;
+  return UV_UNKNOWN_HANDLE;
 }
 
 
diff --git a/src/libuv/src/unix/udp.c b/src/libuv/src/unix/udp.c
index e1a12f2b..3fb8af93 100644
--- a/src/libuv/src/unix/udp.c
+++ b/src/libuv/src/unix/udp.c
@@ -79,7 +79,6 @@ void uv__udp_finish_close(uv_udp_t* handle) {
   }
 
   /* Now tear down the handle. */
-  handle->flags = 0;
   handle->recv_cb = NULL;
   handle->alloc_cb = NULL;
   /* but _do not_ touch close_cb */
diff --git a/src/libuv/src/unix/uv-dtrace.d b/src/libuv/src/unix/uv-dtrace.d
new file mode 100644
index 00000000..7848450c
--- /dev/null
+++ b/src/libuv/src/unix/uv-dtrace.d
@@ -0,0 +1,25 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+provider uv {
+  probe tick__start(void* loop, int mode);
+  probe tick__stop(void* loop, int mode);
+};
diff --git a/src/libuv/src/uv-common.c b/src/libuv/src/uv-common.c
index 8c9d323a..f0792f11 100644
--- a/src/libuv/src/uv-common.c
+++ b/src/libuv/src/uv-common.c
@@ -429,3 +429,8 @@ void uv_unref(uv_handle_t* handle) {
 void uv_stop(uv_loop_t* loop) {
   loop->stop_flag = 1;
 }
+
+
+uint64_t uv_now(uv_loop_t* loop) {
+  return loop->time;
+}
diff --git a/src/libuv/src/uv-common.h b/src/libuv/src/uv-common.h
index 80c9c719..bbf24859 100644
--- a/src/libuv/src/uv-common.h
+++ b/src/libuv/src/uv-common.h
@@ -149,6 +149,9 @@ void uv__fs_poll_close(uv_fs_poll_t* handle);
 #define uv__is_active(h)                                                      \
   (((h)->flags & UV__HANDLE_ACTIVE) != 0)
 
+#define uv__is_closing(h)                                                     \
+  (((h)->flags & (UV_CLOSING |  UV_CLOSED)) != 0)
+
 #define uv__handle_start(h)                                                   \
   do {                                                                        \
     assert(((h)->flags & UV__HANDLE_CLOSING) == 0);                           \
diff --git a/src/libuv/src/version.c b/src/libuv/src/version.c
new file mode 100644
index 00000000..1010b2af
--- /dev/null
+++ b/src/libuv/src/version.c
@@ -0,0 +1,66 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+
+ /*
+ * Versions with an even minor version (e.g. 0.6.1 or 1.0.4) are API and ABI
+ * stable. When the minor version is odd, the API can change between patch
+ * releases. Make sure you update the -soname directives in config-unix.mk
+ * and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but
+ * not UV_VERSION_PATCH.)
+ */
+
+#undef UV_VERSION_MAJOR   /* TODO(bnoordhuis) Remove in v0.11. */
+#undef UV_VERSION_MINOR   /* TODO(bnoordhuis) Remove in v0.11. */
+
+#define UV_VERSION_MAJOR 0
+#define UV_VERSION_MINOR 10
+#define UV_VERSION_PATCH 13
+#define UV_VERSION_IS_RELEASE 1
+
+
+#define UV_VERSION  ((UV_VERSION_MAJOR << 16) | \
+                     (UV_VERSION_MINOR <<  8) | \
+                     (UV_VERSION_PATCH))
+
+#define UV_STRINGIFY(v) UV_STRINGIFY_HELPER(v)
+#define UV_STRINGIFY_HELPER(v) #v
+
+#define UV_VERSION_STRING_BASE  UV_STRINGIFY(UV_VERSION_MAJOR) "." \
+                                UV_STRINGIFY(UV_VERSION_MINOR) "." \
+                                UV_STRINGIFY(UV_VERSION_PATCH)
+
+#if UV_VERSION_IS_RELEASE
+# define UV_VERSION_STRING  UV_VERSION_STRING_BASE
+#else
+# define UV_VERSION_STRING  UV_VERSION_STRING_BASE "-pre"
+#endif
+
+
+unsigned int uv_version(void) {
+  return UV_VERSION;
+}
+
+
+const char* uv_version_string(void) {
+  return UV_VERSION_STRING;
+}
diff --git a/src/libuv/src/win/core.c b/src/libuv/src/win/core.c
index a06c23f3..62d6bf8f 100644
--- a/src/libuv/src/win/core.c
+++ b/src/libuv/src/win/core.c
@@ -55,7 +55,7 @@ static void uv_init(void) {
 
   /* Tell the CRT to not exit the application when an invalid parameter is */
   /* passed. The main issue is that invalid FDs will trigger this behavior. */
-#ifdef _WRITE_ABORT_MSG
+#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800
   _set_invalid_parameter_handler(uv__crt_invalid_parameter_handler);
 #endif
 
@@ -185,7 +185,6 @@ int uv_backend_timeout(const uv_loop_t* loop) {
 
 
 static void uv_poll(uv_loop_t* loop, int block) {
-  BOOL success;
   DWORD bytes, timeout;
   ULONG_PTR key;
   OVERLAPPED* overlapped;
@@ -197,18 +196,16 @@ static void uv_poll(uv_loop_t* loop, int block) {
     timeout = 0;
   }
 
-  success = GetQueuedCompletionStatus(loop->iocp,
-                                      &bytes,
-                                      &key,
-                                      &overlapped,
-                                      timeout);
+  GetQueuedCompletionStatus(loop->iocp,
+                            &bytes,
+                            &key,
+                            &overlapped,
+                            timeout);
 
   if (overlapped) {
     /* Package was dequeued */
     req = uv_overlapped_to_req(overlapped);
-
     uv_insert_pending_req(loop, req);
-
   } else if (GetLastError() != WAIT_TIMEOUT) {
     /* Serious error */
     uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
@@ -230,14 +227,13 @@ static void uv_poll_ex(uv_loop_t* loop, int block) {
     timeout = 0;
   }
 
-  assert(pGetQueuedCompletionStatusEx);
-
   success = pGetQueuedCompletionStatusEx(loop->iocp,
                                          overlappeds,
                                          ARRAY_SIZE(overlappeds),
                                          &count,
                                          timeout,
                                          FALSE);
+
   if (success) {
     for (i = 0; i < count; i++) {
       /* Package was dequeued */
diff --git a/src/libuv/src/win/fs.c b/src/libuv/src/win/fs.c
index 60e67a41..e78bc1b8 100644
--- a/src/libuv/src/win/fs.c
+++ b/src/libuv/src/win/fs.c
@@ -1048,6 +1048,8 @@ static void fs__sendfile(uv_fs_t* req) {
     }
   }
 
+  free(buf);
+
   SET_REQ_RESULT(req, result);
 }
 
@@ -1670,8 +1672,8 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
 }
 
 
-int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid,
-    int gid, uv_fs_cb cb) {
+int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
+    uv_gid_t gid, uv_fs_cb cb) {
   uv_fs_req_init(loop, req, UV_FS_CHOWN, cb);
 
   if (fs__capture_path(loop, req, path, NULL, cb != NULL) < 0) {
@@ -1689,8 +1691,8 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid,
 }
 
 
-int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int uid,
-    int gid, uv_fs_cb cb) {
+int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid,
+    uv_gid_t gid, uv_fs_cb cb) {
   uv_fs_req_init(loop, req, UV_FS_FCHOWN, cb);
 
   if (cb) {
diff --git a/src/libuv/src/win/poll.c b/src/libuv/src/win/poll.c
index 82197241..f6972f96 100644
--- a/src/libuv/src/win/poll.c
+++ b/src/libuv/src/win/poll.c
@@ -311,7 +311,7 @@ static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop,
 static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {
   uv_req_t* req = (uv_req_t*) arg;
   uv_poll_t* handle = (uv_poll_t*) req->data;
-  unsigned char events, reported_events;
+  unsigned char reported_events;
   int r;
   uv_single_fd_set_t rfds, wfds, efds;
   struct timeval timeout;
@@ -319,14 +319,6 @@ static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {
   assert(handle->type == UV_POLL);
   assert(req->type == UV_POLL_REQ);
 
-  if (req == &handle->poll_req_1) {
-    events = handle->submitted_events_1;
-  } else if (req == &handle->poll_req_2) {
-    events = handle->submitted_events_2;
-  } else {
-    assert(0);
-  }
-
   if (handle->events & UV_READABLE) {
     rfds.fd_count = 1;
     rfds.fd_array[0] = handle->socket;
diff --git a/src/libuv/src/win/process.c b/src/libuv/src/win/process.c
index c5649d3a..fb445b6c 100644
--- a/src/libuv/src/win/process.c
+++ b/src/libuv/src/win/process.c
@@ -45,6 +45,51 @@ typedef struct env_var {
 #define E_V(str) { str "=", L##str, sizeof(str), 0, 0 }
 
 
+static HANDLE uv_global_job_handle_;
+static uv_once_t uv_global_job_handle_init_guard_ = UV_ONCE_INIT;
+
+
+static void uv__init_global_job_handle(void) {
+  /* Create a job object and set it up to kill all contained processes when
+   * it's closed. Since this handle is made non-inheritable and we're not
+   * giving it to anyone, we're the only process holding a reference to it.
+   * That means that if this process exits it is closed and all the processes
+   * it contains are killed. All processes created with uv_spawn that are not
+   * spawned with the UV_PROCESS_DETACHED flag are assigned to this job.
+   *
+   * We're setting the JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag so only the
+   * processes that we explicitly add are affected, and *their* subprocesses
+   * are not. This ensures that our child processes are not limited in their
+   * ability to use job control on Windows versions that don't deal with
+   * nested jobs (prior to Windows 8 / Server 2012). It also lets our child
+   * processes created detached processes without explicitly breaking away
+   * from job control (which uv_spawn doesn't, either).
+   */
+  SECURITY_ATTRIBUTES attr;
+  JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
+
+  memset(&attr, 0, sizeof attr);
+  attr.bInheritHandle = FALSE;
+
+  memset(&info, 0, sizeof info);
+  info.BasicLimitInformation.LimitFlags =
+      JOB_OBJECT_LIMIT_BREAKAWAY_OK |
+      JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK |
+      JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION |
+      JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+
+  uv_global_job_handle_ = CreateJobObjectW(&attr, NULL);
+  if (uv_global_job_handle_ == NULL)
+    uv_fatal_error(GetLastError(), "CreateJobObjectW");
+
+  if (!SetInformationJobObject(uv_global_job_handle_,
+                               JobObjectExtendedLimitInformation,
+                               &info,
+                               sizeof info))
+    uv_fatal_error(GetLastError(), "SetInformationJobObject");
+}
+
+
 static uv_err_t uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) {
   int ws_len, r;
   WCHAR* ws;
@@ -180,7 +225,7 @@ static WCHAR* search_path_join_test(const WCHAR* dir,
   attrs = GetFileAttributesW(result);
 
   if (attrs != INVALID_FILE_ATTRIBUTES &&
-     !(attrs & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))) {
+      !(attrs & FILE_ATTRIBUTE_DIRECTORY)) {
     return result;
   }
 
@@ -890,7 +935,18 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
   }
 
   process_flags = CREATE_UNICODE_ENVIRONMENT;
+
   if (options.flags & UV_PROCESS_DETACHED) {
+    /* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That
+     * means that libuv might not let you create a fully deamonized process
+     * when run under job control. However the type of job control that libuv
+     * itself creates doesn't trickle down to subprocesses so they can still
+     * daemonize.
+     *
+     * A reason to not do this is that CREATE_BREAKAWAY_FROM_JOB makes the
+     * CreateProcess call fail if we're under job control that doesn't allow
+     * breakaway.
+     */
     process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
   }
 
@@ -908,6 +964,28 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
     process->process_handle = info.hProcess;
     process->pid = info.dwProcessId;
 
+    /* If the process isn't spawned as detached, assign to the global job */
+    /* object so windows will kill it when the parent process dies. */
+    if (!(options.flags & UV_PROCESS_DETACHED)) {
+      uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);
+
+      if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) {
+        /* AssignProcessToJobObject might fail if this process is under job
+         * control and the job doesn't have the
+         * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version
+         * that doesn't support nested jobs.
+         *
+         * When that happens we just swallow the error and continue without
+         * establishing a kill-child-on-parent-exit relationship, otherwise
+         * there would be no way for libuv applications run under job control
+         * to spawn processes at all.
+         */
+        DWORD err = GetLastError();
+        if (err != ERROR_ACCESS_DENIED)
+          uv_fatal_error(err, "AssignProcessToJobObject");
+      }
+    }
+
     /* Set IPC pid to all IPC pipes. */
     for (i = 0; i < options.stdio_count; i++) {
       const uv_stdio_container_t* fdopt = &options.stdio[i];
diff --git a/src/libuv/src/win/stream.c b/src/libuv/src/win/stream.c
index 097f3497..edc5407c 100644
--- a/src/libuv/src/win/stream.c
+++ b/src/libuv/src/win/stream.c
@@ -56,7 +56,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
 int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,
     uv_read_cb read_cb) {
   if (handle->flags & UV_HANDLE_READING) {
-    uv__set_sys_error(handle->loop, UV_EALREADY);
+    uv__set_artificial_error(handle->loop, UV_EALREADY);
     return -1;
   }
 
@@ -82,7 +82,7 @@ int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,
 int uv_read2_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,
     uv_read2_cb read_cb) {
   if (handle->flags & UV_HANDLE_READING) {
-    uv__set_sys_error(handle->loop, UV_EALREADY);
+    uv__set_artificial_error(handle->loop, UV_EALREADY);
     return -1;
   }
 
diff --git a/src/libuv/src/win/tcp.c b/src/libuv/src/win/tcp.c
index c3ef6533..59a36de0 100644
--- a/src/libuv/src/win/tcp.c
+++ b/src/libuv/src/win/tcp.c
@@ -50,7 +50,7 @@ static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) {
                  TCP_NODELAY,
                  (const char*)&enable,
                  sizeof enable) == -1) {
-    uv__set_sys_error(handle->loop, errno);
+    uv__set_sys_error(handle->loop, WSAGetLastError());
     return -1;
   }
   return 0;
@@ -63,7 +63,7 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign
                  SO_KEEPALIVE,
                  (const char*)&enable,
                  sizeof enable) == -1) {
-    uv__set_sys_error(handle->loop, errno);
+    uv__set_sys_error(handle->loop, WSAGetLastError());
     return -1;
   }
 
@@ -72,7 +72,7 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign
                            TCP_KEEPALIVE,
                            (const char*)&delay,
                            sizeof delay) == -1) {
-    uv__set_sys_error(handle->loop, errno);
+    uv__set_sys_error(handle->loop, WSAGetLastError());
     return -1;
   }
 
diff --git a/src/libuv/src/win/timer.c b/src/libuv/src/win/timer.c
index 0c055da9..8dae7414 100644
--- a/src/libuv/src/win/timer.c
+++ b/src/libuv/src/win/timer.c
@@ -45,11 +45,6 @@ void uv_update_time(uv_loop_t* loop) {
 }
 
 
-uint64_t uv_now(uv_loop_t* loop) {
-  return loop->time;
-}
-
-
 static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) {
   if (a->due < b->due)
     return -1;
@@ -87,6 +82,17 @@ void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) {
 }
 
 
+static uint64_t get_clamped_due_time(uint64_t loop_time, uint64_t timeout) {
+  uint64_t clamped_timeout;
+
+  clamped_timeout = loop_time + timeout;
+  if (clamped_timeout < timeout)
+    clamped_timeout = (uint64_t) -1;
+
+  return clamped_timeout;
+}
+
+
 int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout,
     uint64_t repeat) {
   uv_loop_t* loop = handle->loop;
@@ -97,7 +103,7 @@ int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout,
   }
 
   handle->timer_cb = timer_cb;
-  handle->due = loop->time + timeout;
+  handle->due = get_clamped_due_time(loop->time, timeout);
   handle->repeat = repeat;
   handle->flags |= UV_HANDLE_ACTIVE;
   uv__handle_start(handle);
@@ -143,7 +149,7 @@ int uv_timer_again(uv_timer_t* handle) {
   }
 
   if (handle->repeat) {
-    handle->due = loop->time + handle->repeat;
+    handle->due = get_clamped_due_time(loop->time, handle->repeat);
 
     if (RB_INSERT(uv_timer_tree_s, &loop->timers, handle) != NULL) {
       uv_fatal_error(ERROR_INVALID_DATA, "RB_INSERT");
@@ -212,7 +218,7 @@ void uv_process_timers(uv_loop_t* loop) {
 
     if (timer->repeat != 0) {
       /* If it is a repeating timer, reschedule with repeat timeout. */
-      timer->due += timer->repeat;
+      timer->due = get_clamped_due_time(timer->due, timer->repeat);
       if (timer->due < loop->time) {
         timer->due = loop->time;
       }
diff --git a/src/libuv/src/win/tty.c b/src/libuv/src/win/tty.c
index 8f7e7657..64934ffa 100644
--- a/src/libuv/src/win/tty.c
+++ b/src/libuv/src/win/tty.c
@@ -96,7 +96,7 @@ void uv_console_init() {
 
 
 int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
-  HANDLE handle = INVALID_HANDLE_VALUE;
+  HANDLE handle;
   CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
 
   handle = (HANDLE) _get_osfhandle(fd);
diff --git a/src/libuv/src/win/udp.c b/src/libuv/src/win/udp.c
index b6b6e0f7..4dcb19d8 100644
--- a/src/libuv/src/win/udp.c
+++ b/src/libuv/src/win/udp.c
@@ -182,7 +182,7 @@ static int uv__bind(uv_udp_t* handle,
                     int addrsize,
                     unsigned int flags) {
   int r;
-  DWORD no = 0, yes = 1;
+  DWORD no = 0;
 
   if ((flags & UV_UDP_IPV6ONLY) && family != AF_INET6) {
     /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */
@@ -658,7 +658,6 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
 int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
   WSAPROTOCOL_INFOW protocol_info;
   int opt_len;
-  DWORD yes = 1;
 
   /* Detect the address family of the socket. */
   opt_len = (int) sizeof protocol_info;
diff --git a/src/libuv/src/win/util.c b/src/libuv/src/win/util.c
index 362d12c9..4dd07363 100644
--- a/src/libuv/src/win/util.c
+++ b/src/libuv/src/win/util.c
@@ -580,47 +580,50 @@ uv_err_t uv_uptime(double* uptime) {
 }
 
 
-uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
+uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
+  uv_cpu_info_t* cpu_infos;
   SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
   DWORD sppi_size;
   SYSTEM_INFO system_info;
-  DWORD cpu_count, i, r;
+  DWORD cpu_count, r, i;
+  NTSTATUS status;
   ULONG result_size;
-  size_t size;
   uv_err_t err;
   uv_cpu_info_t* cpu_info;
 
-  *cpu_infos = NULL;
-  *count = 0;
+  cpu_infos = NULL;
+  cpu_count = 0;
+  sppi = NULL;
 
   uv__once_init();
 
   GetSystemInfo(&system_info);
   cpu_count = system_info.dwNumberOfProcessors;
 
-  size = cpu_count * sizeof(uv_cpu_info_t);
-  *cpu_infos = (uv_cpu_info_t*) malloc(size);
-  if (*cpu_infos == NULL) {
+  cpu_infos = calloc(cpu_count, sizeof *cpu_infos);
+  if (cpu_infos == NULL) {
     err = uv__new_artificial_error(UV_ENOMEM);
-    goto out;
+    goto error;
   }
-  memset(*cpu_infos, 0, size);
 
-  sppi_size = sizeof(*sppi) * cpu_count;
-  sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*) malloc(sppi_size);
-  if (!sppi) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+  sppi_size = cpu_count * sizeof(*sppi);
+  sppi = malloc(sppi_size);
+  if (sppi == NULL) {
+    err = uv__new_artificial_error(UV_ENOMEM);
+    goto error;
   }
 
-  r = pNtQuerySystemInformation(SystemProcessorPerformanceInformation,
-                                sppi,
-                                sppi_size,
-                                &result_size);
-  if (r != ERROR_SUCCESS || result_size != sppi_size) {
-    err = uv__new_sys_error(GetLastError());
-    goto out;
+  status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation,
+                                     sppi,
+                                     sppi_size,
+                                     &result_size);
+  if (!NT_SUCCESS(status)) {
+    err = uv__new_sys_error(pRtlNtStatusToDosError(status));
+    goto error;
   }
 
+  assert(result_size == sppi_size);
+
   for (i = 0; i < cpu_count; i++) {
     WCHAR key_name[128];
     HKEY processor_key;
@@ -628,11 +631,14 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
     DWORD cpu_speed_size = sizeof(cpu_speed);
     WCHAR cpu_brand[256];
     DWORD cpu_brand_size = sizeof(cpu_brand);
+    int len;
 
-    _snwprintf(key_name,
-               ARRAY_SIZE(key_name),
-               L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d",
-               i);
+    len = _snwprintf(key_name,
+                     ARRAY_SIZE(key_name),
+                     L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d",
+                     i);
+
+    assert(len > 0 && len < ARRAY_SIZE(key_name));
 
     r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
                       key_name,
@@ -641,32 +647,34 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
                       &processor_key);
     if (r != ERROR_SUCCESS) {
       err = uv__new_sys_error(GetLastError());
-      goto out;
+      goto error;
     }
 
     if (RegQueryValueExW(processor_key,
                          L"~MHz",
-                         NULL, NULL,
+                         NULL,
+                         NULL,
                          (BYTE*) &cpu_speed,
                          &cpu_speed_size) != ERROR_SUCCESS) {
       err = uv__new_sys_error(GetLastError());
       RegCloseKey(processor_key);
-      goto out;
+      goto error;
     }
 
     if (RegQueryValueExW(processor_key,
                          L"ProcessorNameString",
-                         NULL, NULL,
+                         NULL,
+                         NULL,
                          (BYTE*) &cpu_brand,
                          &cpu_brand_size) != ERROR_SUCCESS) {
       err = uv__new_sys_error(GetLastError());
       RegCloseKey(processor_key);
-      goto out;
+      goto error;
     }
 
     RegCloseKey(processor_key);
 
-    cpu_info = &(*cpu_infos)[i];
+    cpu_info = &cpu_infos[i];
     cpu_info->speed = cpu_speed;
     cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000;
     cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart -
@@ -675,57 +683,59 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
     cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000;
     cpu_info->cpu_times.nice = 0;
 
-    size = uv_utf16_to_utf8(cpu_brand,
-                            cpu_brand_size / sizeof(WCHAR),
-                            NULL,
-                            0);
-    if (size == 0) {
+
+    len = WideCharToMultiByte(CP_UTF8,
+                              0,
+                              cpu_brand,
+                              cpu_brand_size / sizeof(WCHAR),
+                              NULL,
+                              0,
+                              NULL,
+                              NULL);
+    if (len == 0) {
       err = uv__new_sys_error(GetLastError());
-      goto out;
+      goto error;
     }
 
+    assert(len > 0);
+
     /* Allocate 1 extra byte for the null terminator. */
-    cpu_info->model = (char*) malloc(size + 1);
+    cpu_info->model = malloc(len + 1);
     if (cpu_info->model == NULL) {
       err = uv__new_artificial_error(UV_ENOMEM);
-      goto out;
+      goto error;
     }
 
-    if (uv_utf16_to_utf8(cpu_brand,
-                         cpu_brand_size / sizeof(WCHAR),
-                         cpu_info->model,
-                         size) == 0) {
+    if (WideCharToMultiByte(CP_UTF8,
+                            0,
+                            cpu_brand,
+                            cpu_brand_size / sizeof(WCHAR),
+                            cpu_info->model,
+                            len,
+                            NULL,
+                            NULL) == 0) {
       err = uv__new_sys_error(GetLastError());
-      goto out;
+      goto error;
     }
 
     /* Ensure that cpu_info->model is null terminated. */
-    cpu_info->model[size] = '\0';
-
-    (*count)++;
+    cpu_info->model[len] = '\0';
   }
 
-  err = uv_ok_;
+  free(sppi);
 
- out:
-  if (sppi) {
-    free(sppi);
-  }
+  *cpu_count_ptr = cpu_count;
+  *cpu_infos_ptr = cpu_infos;
 
-  if (err.code != UV_OK &&
-      *cpu_infos != NULL) {
-    int i;
+  return uv_ok_;
 
-    for (i = 0; i < *count; i++) {
-      /* This is safe because the cpu_infos memory area is zeroed out */
-      /* immediately after allocating it. */
-      free((*cpu_infos)[i].model);
-    }
-    free(*cpu_infos);
+ error:
+  /* This is safe because the cpu_infos array is zeroed on allocation. */
+  for (i = 0; i < cpu_count; i++)
+    free(cpu_infos[i].model);
 
-    *cpu_infos = NULL;
-    *count = 0;
-  }
+  free(cpu_infos);
+  free(sppi);
 
   return err;
 }
diff --git a/src/libuv/src/win/winsock.c b/src/libuv/src/win/winsock.c
index 47395bb8..cf6d0318 100644
--- a/src/libuv/src/win/winsock.c
+++ b/src/libuv/src/win/winsock.c
@@ -79,12 +79,6 @@ static int error_means_no_support(DWORD error) {
 
 
 void uv_winsock_init() {
-  const GUID wsaid_connectex            = WSAID_CONNECTEX;
-  const GUID wsaid_acceptex             = WSAID_ACCEPTEX;
-  const GUID wsaid_getacceptexsockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
-  const GUID wsaid_disconnectex         = WSAID_DISCONNECTEX;
-  const GUID wsaid_transmitfile         = WSAID_TRANSMITFILE;
-
   WSADATA wsa_data;
   int errorno;
   SOCKET dummy;
diff --git a/src/libuv/test/runner-unix.c b/src/libuv/test/runner-unix.c
index eefb7008..b66df51b 100644
--- a/src/libuv/test/runner-unix.c
+++ b/src/libuv/test/runner-unix.c
@@ -286,6 +286,34 @@ int process_copy_output(process_info_t *p, int fd) {
 }
 
 
+/* Copy the last line of the stdio output buffer to `buffer` */
+int process_read_last_line(process_info_t *p,
+                           char* buffer,
+                           size_t buffer_len) {
+  char* ptr;
+
+  int r = fseek(p->stdout_file, 0, SEEK_SET);
+  if (r < 0) {
+    perror("fseek");
+    return -1;
+  }
+
+  buffer[0] = '\0';
+
+  while (fgets(buffer, buffer_len, p->stdout_file) != NULL) {
+    for (ptr = buffer; *ptr && *ptr != '\r' && *ptr != '\n'; ptr++);
+    *ptr = '\0';
+  }
+
+  if (ferror(p->stdout_file)) {
+    perror("read");
+    buffer[0] = '\0';
+    return -1;
+  }
+  return 0;
+}
+
+
 /* Return the name that was specified when `p` was started by process_start */
 char* process_get_name(process_info_t *p) {
   return p->name;
diff --git a/src/libuv/test/runner-win.c b/src/libuv/test/runner-win.c
index 8f534bcd..5d232594 100644
--- a/src/libuv/test/runner-win.c
+++ b/src/libuv/test/runner-win.c
@@ -44,6 +44,11 @@
 
 /* Do platform-specific initialization. */
 void platform_init(int argc, char **argv) {
+  const char* tap;
+
+  tap = getenv("UV_TAP_OUTPUT");
+  tap_output = (tap != NULL && atoi(tap) > 0);
+
   /* Disable the "application crashed" popup. */
   SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
       SEM_NOOPENFILEERRORBOX);
@@ -207,13 +212,34 @@ long int process_output_size(process_info_t *p) {
 int process_copy_output(process_info_t *p, int fd) {
   DWORD read;
   char buf[1024];
+  char *line, *start;
 
   if (SetFilePointer(p->stdio_out, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
     return -1;
 
+  if (tap_output)
+    write(fd, "#", 1);
+
   while (ReadFile(p->stdio_out, (void*)&buf, sizeof(buf), &read, NULL) &&
-         read > 0)
-    write(fd, buf, read);
+         read > 0) {
+    if (tap_output) {
+      start = buf;
+
+      while ((line = strchr(start, '\n')) != NULL) {
+        write(fd, start, line - start + 1);
+        write(fd, "#", 1);
+        start = line + 1;
+      }
+
+      if (start < buf + read)
+        write(fd, start, buf + read - start);
+    } else {
+      write(fd, buf, read);
+    }
+  }
+
+  if (tap_output)
+    write(fd, "\n", 1);
 
   if (GetLastError() != ERROR_HANDLE_EOF)
     return -1;
@@ -222,6 +248,46 @@ int process_copy_output(process_info_t *p, int fd) {
 }
 
 
+int process_read_last_line(process_info_t *p,
+                           char * buffer,
+                           size_t buffer_len) {
+  DWORD size;
+  DWORD read;
+  DWORD start;
+  OVERLAPPED overlapped;
+
+  ASSERT(buffer_len > 0);
+
+  size = GetFileSize(p->stdio_out, NULL);
+  if (size == INVALID_FILE_SIZE)
+    return -1;
+
+  if (size == 0) {
+    buffer[0] = '\0';
+    return 1;
+  }
+
+  memset(&overlapped, 0, sizeof overlapped);
+  if (size >= buffer_len)
+    overlapped.Offset = size - buffer_len - 1;
+
+  if (!ReadFile(p->stdio_out, buffer, buffer_len - 1, &read, &overlapped))
+    return -1;
+
+  for (start = read - 1; start >= 0; start--) {
+    if (buffer[start] == '\n' || buffer[start] == '\r')
+      break;
+  }
+
+  if (start > 0)
+    memmove(buffer, buffer + start, read - start);
+
+  buffer[read - start] = '\0';
+
+  return 0;
+}
+
+
 char* process_get_name(process_info_t *p) {
   return p->name;
 }
diff --git a/src/libuv/test/runner.c b/src/libuv/test/runner.c
index bda1080a..d8e9ddeb 100644
--- a/src/libuv/test/runner.c
+++ b/src/libuv/test/runner.c
@@ -31,12 +31,25 @@ char executable_path[PATHMAX] = { '\0' };
 int tap_output = 0;
 
 
-static void log_progress(int total, int passed, int failed, const char* name) {
+static void log_progress(int total,
+                         int passed,
+                         int failed,
+                         int todos,
+                         int skipped,
+                         const char* name) {
+  int progress;
+
   if (total == 0)
     total = 1;
 
-  LOGF("[%% %3d|+ %3d|- %3d]: %s", (int) ((passed + failed) / ((double) total) * 100.0),
-      passed, failed, name);
+  progress = 100 * (passed + failed + skipped + todos) / total;
+  LOGF("[%% %3d|+ %3d|- %3d|T %3d|S %3d]: %s",
+       progress,
+       passed,
+       failed,
+       todos,
+       skipped,
+       name);
 }
 
 
@@ -78,7 +91,13 @@ const char* fmt(double d) {
 
 
 int run_tests(int timeout, int benchmark_output) {
-  int total, passed, failed, current;
+  int total;
+  int passed;
+  int failed;
+  int todos;
+  int skipped;
+  int current;
+  int test_result;
   task_entry_t* task;
 
   /* Count the number of tests. */
@@ -96,6 +115,8 @@ int run_tests(int timeout, int benchmark_output) {
   /* Run all tests. */
   passed = 0;
   failed = 0;
+  todos = 0;
+  skipped = 0;
   current = 1;
   for (task = TASKS; task->main; task++) {
     if (task->is_helper) {
@@ -106,13 +127,15 @@ int run_tests(int timeout, int benchmark_output) {
       rewind_cursor();
 
     if (!benchmark_output && !tap_output) {
-      log_progress(total, passed, failed, task->task_name);
+      log_progress(total, passed, failed, todos, skipped, task->task_name);
     }
 
-    if (run_test(task->task_name, timeout, benchmark_output, current) == 0) {
-      passed++;
-    } else {
-      failed++;
+    test_result = run_test(task->task_name, timeout, benchmark_output, current);
+    switch (test_result) {
+    case TEST_OK: passed++; break;
+    case TEST_TODO: todos++; break;
+    case TEST_SKIP: skipped++; break;
+    default: failed++;
     }
     current++;
   }
@@ -121,13 +144,50 @@ int run_tests(int timeout, int benchmark_output) {
     rewind_cursor();
 
   if (!benchmark_output && !tap_output) {
-    log_progress(total, passed, failed, "Done.\n");
+    log_progress(total, passed, failed, todos, skipped, "Done.\n");
   }
 
   return failed;
 }
 
 
+void log_tap_result(int test_count,
+                    const char* test,
+                    int status,
+                    process_info_t* process) {
+  const char* result;
+  const char* directive;
+  char reason[1024];
+
+  switch (status) {
+  case TEST_OK:
+    result = "ok";
+    directive = "";
+    break;
+  case TEST_TODO:
+    result = "not ok";
+    directive = " # TODO ";
+    break;
+  case TEST_SKIP:
+    result = "ok";
+    directive = " # SKIP ";
+    break;
+  default:
+    result = "not ok";
+    directive = "";
+  }
+
+  if ((status == TEST_SKIP || status == TEST_TODO) &&
+      process_output_size(process) > 0) {
+    process_read_last_line(process, reason, sizeof reason);
+  } else {
+    reason[0] = '\0';
+  }
+
+  LOGF("%s %d - %s%s%s\n", result, test_count, test, directive, reason);
+}
+
+
 int run_test(const char* test,
              int timeout,
              int benchmark_output,
@@ -231,7 +291,7 @@ int run_test(const char* test,
   }
 
   status = process_reap(main_proc);
-  if (status != 0) {
+  if (status != TEST_OK) {
     snprintf(errmsg,
              sizeof errmsg,
              "exit code %d",
@@ -255,17 +315,17 @@ int run_test(const char* test,
     FATAL("process_wait failed");
   }
 
-  if (tap_output) {
-    if (status == 0)
-      LOGF("ok %d - %s\n", test_count, test);
-    else
-      LOGF("not ok %d - %s\n", test_count, test);
-  }
+  if (tap_output)
+    log_tap_result(test_count, test, status, &processes[i]);
 
   /* Show error and output from processes if the test failed. */
   if (status != 0 || task->show_output) {
     if (tap_output) {
       LOGF("#");
+    } else if (status == TEST_TODO) {
+      LOGF("\n`%s` todo\n", test);
+    } else if (status == TEST_SKIP) {
+      LOGF("\n`%s` skipped\n", test);
     } else if (status != 0) {
       LOGF("\n`%s` failed: %s\n", test, errmsg);
     } else {
diff --git a/src/libuv/test/runner.h b/src/libuv/test/runner.h
index 8be9e39f..aa7f2054 100644
--- a/src/libuv/test/runner.h
+++ b/src/libuv/test/runner.h
@@ -143,6 +143,11 @@ long int process_output_size(process_info_t *p);
 /* Copy the contents of the stdio output buffer to `fd`. */
 int process_copy_output(process_info_t *p, int fd);
 
+/* Copy the last line of the stdio output buffer to `buffer` */
+int process_read_last_line(process_info_t *p,
+                           char * buffer,
+                           size_t buffer_len);
+
 /* Return the name that was specified when `p` was started by process_start */
 char* process_get_name(process_info_t *p);
 
diff --git a/src/libuv/test/task.h b/src/libuv/test/task.h
index de7c80ec..308201e5 100644
--- a/src/libuv/test/task.h
+++ b/src/libuv/test/task.h
@@ -119,4 +119,28 @@ void uv_sleep(int msec);
 /* Format big numbers nicely. WARNING: leaks memory. */
 const char* fmt(double d);
 
+/* Reserved test exit codes. */
+enum test_status {
+  TEST_OK = 0,
+  TEST_TODO,
+  TEST_SKIP
+};
+
+#define RETURN_OK()                                                           \
+  do {                                                                        \
+    return TEST_OK;                                                           \
+  } while (0)
+
+#define RETURN_TODO(explanation)                                              \
+  do {                                                                        \
+    LOGF("%s\n", explanation);                                                \
+    return TEST_TODO;                                                         \
+  } while (0)
+
+#define RETURN_SKIP(explanation)                                              \
+  do {                                                                        \
+    LOGF("%s\n", explanation);                                                \
+    return TEST_SKIP;                                                         \
+  } while (0)
+
 #endif /* TASK_H_ */
diff --git a/src/libuv/test/test-fs.c b/src/libuv/test/test-fs.c
index 0016b3be..ca2ff2bd 100644
--- a/src/libuv/test/test-fs.c
+++ b/src/libuv/test/test-fs.c
@@ -1391,7 +1391,8 @@ TEST_IMPL(fs_symlink_dir) {
 #ifdef _WIN32
   ASSERT(((struct stat*)req.ptr)->st_size == strlen(test_dir + 4));
 #else
-  ASSERT(((struct stat*)req.ptr)->st_size == strlen(test_dir));
+  /* st_size has type off_t. Cast to avoid signed/unsigned warnings. */
+  ASSERT((size_t) ((struct stat*)req.ptr)->st_size == strlen(test_dir));
 #endif
   uv_fs_req_cleanup(&req);
 
diff --git a/src/libuv/test/test-list.h b/src/libuv/test/test-list.h
index 2341463a..7a9b1a29 100644
--- a/src/libuv/test/test-list.h
+++ b/src/libuv/test/test-list.h
@@ -95,9 +95,13 @@ TEST_DECLARE   (shutdown_eof)
 TEST_DECLARE   (callback_stack)
 TEST_DECLARE   (error_message)
 TEST_DECLARE   (timer)
+TEST_DECLARE   (timer_init)
 TEST_DECLARE   (timer_again)
 TEST_DECLARE   (timer_start_twice)
 TEST_DECLARE   (timer_order)
+TEST_DECLARE   (timer_huge_timeout)
+TEST_DECLARE   (timer_huge_repeat)
+TEST_DECLARE   (timer_from_check)
 TEST_DECLARE   (idle_starvation)
 TEST_DECLARE   (loop_handles)
 TEST_DECLARE   (get_loadavg)
@@ -217,6 +221,9 @@ TEST_DECLARE   (we_get_signal)
 TEST_DECLARE   (we_get_signals)
 TEST_DECLARE   (signal_multiple_loops)
 #endif
+#ifdef __APPLE__
+TEST_DECLARE   (osx_select)
+#endif
 HELPER_DECLARE (tcp4_echo_server)
 HELPER_DECLARE (tcp6_echo_server)
 HELPER_DECLARE (udp4_echo_server)
@@ -336,9 +343,13 @@ TASK_LIST_START
   TEST_ENTRY  (error_message)
 
   TEST_ENTRY  (timer)
+  TEST_ENTRY  (timer_init)
   TEST_ENTRY  (timer_again)
   TEST_ENTRY  (timer_start_twice)
   TEST_ENTRY  (timer_order)
+  TEST_ENTRY  (timer_huge_timeout)
+  TEST_ENTRY  (timer_huge_repeat)
+  TEST_ENTRY  (timer_from_check)
 
   TEST_ENTRY  (idle_starvation)
 
@@ -434,6 +445,10 @@ TASK_LIST_START
   TEST_ENTRY  (signal_multiple_loops)
 #endif
 
+#ifdef __APPLE__
+  TEST_ENTRY (osx_select)
+#endif
+
   TEST_ENTRY  (fs_file_noent)
   TEST_ENTRY  (fs_file_nametoolong)
   TEST_ENTRY  (fs_file_loop)
diff --git a/src/libuv/test/test-osx-select.c b/src/libuv/test/test-osx-select.c
new file mode 100644
index 00000000..bf4c3952
--- /dev/null
+++ b/src/libuv/test/test-osx-select.c
@@ -0,0 +1,82 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+#ifdef __APPLE__
+
+#include <sys/ioctl.h>
+#include <string.h>
+
+static int read_count;
+
+
+static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
+  static char buf[1024];
+
+  return uv_buf_init(buf, ARRAY_SIZE(buf));
+}
+
+
+static void read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) {
+  fprintf(stdout, "got data %d\n", ++read_count);
+
+  if (read_count == 3)
+    uv_close((uv_handle_t*) stream, NULL);
+}
+
+
+TEST_IMPL(osx_select) {
+  int r;
+  int fd;
+  size_t i;
+  size_t len;
+  const char* str;
+  uv_tty_t tty;
+
+  fd = open("/dev/tty", O_RDONLY);
+
+  ASSERT(fd >= 0);
+
+  r = uv_tty_init(uv_default_loop(), &tty, fd, 1);
+  ASSERT(r == 0);
+
+  uv_read_start((uv_stream_t*) &tty, alloc_cb, read_cb);
+
+  /* Emulate user-input */
+  str = "got some input\n"
+        "with a couple of lines\n"
+        "feel pretty happy\n";
+  for (i = 0, len = strlen(str); i < len; i++) {
+    r = ioctl(fd, TIOCSTI, str + i);
+    ASSERT(r == 0);
+  }
+
+  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+  ASSERT(read_count == 3);
+
+  MAKE_VALGRIND_HAPPY();
+  return 0;
+}
+
+#endif /* __APPLE__ */
diff --git a/src/libuv/test/test-process-title.c b/src/libuv/test/test-process-title.c
index 13d9dddf..c870abd1 100644
--- a/src/libuv/test/test-process-title.c
+++ b/src/libuv/test/test-process-title.c
@@ -42,8 +42,12 @@ static void set_title(const char* title) {
 
 
 TEST_IMPL(process_title) {
+#if defined(__sun)
+  RETURN_SKIP("uv_(get|set)_process_title is not implemented.");
+#else
   /* Check for format string vulnerabilities. */
-  set_title("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s");
+  set_title("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s");
   set_title("new title");
   return 0;
+#endif
 }
diff --git a/src/libuv/test/test-tcp-writealot.c b/src/libuv/test/test-tcp-writealot.c
index 3ddcd6d2..ab8c46ad 100644
--- a/src/libuv/test/test-tcp-writealot.c
+++ b/src/libuv/test/test-tcp-writealot.c
@@ -26,8 +26,8 @@
 
 
 #define WRITES            3
-#define CHUNKS_PER_WRITE  3
-#define CHUNK_SIZE        10485760 /* 10 MB */
+#define CHUNKS_PER_WRITE  4096
+#define CHUNK_SIZE        10024 /* 10 kb */
 
 #define TOTAL_BYTES       (WRITES * CHUNKS_PER_WRITE * CHUNK_SIZE)
 
diff --git a/src/libuv/test/test-timer-from-check.c b/src/libuv/test/test-timer-from-check.c
new file mode 100644
index 00000000..2aa3fe41
--- /dev/null
+++ b/src/libuv/test/test-timer-from-check.c
@@ -0,0 +1,80 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+static uv_prepare_t prepare_handle;
+static uv_check_t check_handle;
+static uv_timer_t timer_handle;
+
+static int prepare_cb_called;
+static int check_cb_called;
+static int timer_cb_called;
+
+
+static void prepare_cb(uv_prepare_t* handle, int status) {
+  ASSERT(0 == uv_prepare_stop(&prepare_handle));
+  ASSERT(0 == prepare_cb_called);
+  ASSERT(1 == check_cb_called);
+  ASSERT(0 == timer_cb_called);
+  prepare_cb_called++;
+}
+
+
+static void timer_cb(uv_timer_t* handle, int status) {
+  ASSERT(0 == uv_timer_stop(&timer_handle));
+  ASSERT(1 == prepare_cb_called);
+  ASSERT(1 == check_cb_called);
+  ASSERT(0 == timer_cb_called);
+  timer_cb_called++;
+}
+
+
+static void check_cb(uv_check_t* handle, int status) {
+  ASSERT(0 == uv_check_stop(&check_handle));
+  ASSERT(0 == uv_timer_stop(&timer_handle));  /* Runs before timer_cb. */
+  ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 50, 0));
+  ASSERT(0 == uv_prepare_start(&prepare_handle, prepare_cb));
+  ASSERT(0 == prepare_cb_called);
+  ASSERT(0 == check_cb_called);
+  ASSERT(0 == timer_cb_called);
+  check_cb_called++;
+}
+
+
+TEST_IMPL(timer_from_check) {
+  ASSERT(0 == uv_prepare_init(uv_default_loop(), &prepare_handle));
+  ASSERT(0 == uv_check_init(uv_default_loop(), &check_handle));
+  ASSERT(0 == uv_check_start(&check_handle, check_cb));
+  ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle));
+  ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 50, 0));
+  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+  ASSERT(1 == prepare_cb_called);
+  ASSERT(1 == check_cb_called);
+  ASSERT(1 == timer_cb_called);
+  uv_close((uv_handle_t*) &prepare_handle, NULL);
+  uv_close((uv_handle_t*) &check_handle, NULL);
+  uv_close((uv_handle_t*) &timer_handle, NULL);
+  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
+  MAKE_VALGRIND_HAPPY();
+  return 0;
+}
diff --git a/src/libuv/test/test-timer.c b/src/libuv/test/test-timer.c
index 60b080d2..6aa28897 100644
--- a/src/libuv/test/test-timer.c
+++ b/src/libuv/test/test-timer.c
@@ -28,8 +28,10 @@ static int once_close_cb_called = 0;
 static int repeat_cb_called = 0;
 static int repeat_close_cb_called = 0;
 static int order_cb_called = 0;
-
 static uint64_t start_time;
+static uv_timer_t tiny_timer;
+static uv_timer_t huge_timer1;
+static uv_timer_t huge_timer2;
 
 
 static void once_close_cb(uv_handle_t* handle) {
@@ -156,6 +158,18 @@ TEST_IMPL(timer_start_twice) {
 }
 
 
+TEST_IMPL(timer_init) {
+  uv_timer_t handle;
+
+  ASSERT(0 == uv_timer_init(uv_default_loop(), &handle));
+  ASSERT(0 == uv_timer_get_repeat(&handle));
+  ASSERT(!uv_is_active((uv_handle_t*)&handle));
+
+  MAKE_VALGRIND_HAPPY();
+  return 0;
+}
+
+
 static void order_cb_a(uv_timer_t *handle, int status) {
   ASSERT(order_cb_called++ == *(int*)handle->data);
 }
@@ -200,5 +214,53 @@ TEST_IMPL(timer_order) {
 
   ASSERT(order_cb_called == 2);
 
+  MAKE_VALGRIND_HAPPY();
+  return 0;
+}
+
+
+static void tiny_timer_cb(uv_timer_t* handle, int status) {
+  ASSERT(handle == &tiny_timer);
+  uv_close((uv_handle_t*) &tiny_timer, NULL);
+  uv_close((uv_handle_t*) &huge_timer1, NULL);
+  uv_close((uv_handle_t*) &huge_timer2, NULL);
+}
+
+
+TEST_IMPL(timer_huge_timeout) {
+  ASSERT(0 == uv_timer_init(uv_default_loop(), &tiny_timer));
+  ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer1));
+  ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer2));
+  ASSERT(0 == uv_timer_start(&tiny_timer, tiny_timer_cb, 1, 0));
+  ASSERT(0 == uv_timer_start(&huge_timer1, tiny_timer_cb, 0xffffffffffffLL, 0));
+  ASSERT(0 == uv_timer_start(&huge_timer2, tiny_timer_cb, (uint64_t) -1, 0));
+  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+  MAKE_VALGRIND_HAPPY();
+  return 0;
+}
+
+
+static void huge_repeat_cb(uv_timer_t* handle, int status) {
+  static int ncalls;
+
+  if (ncalls == 0)
+    ASSERT(handle == &huge_timer1);
+  else
+    ASSERT(handle == &tiny_timer);
+
+  if (++ncalls == 10) {
+    uv_close((uv_handle_t*) &tiny_timer, NULL);
+    uv_close((uv_handle_t*) &huge_timer1, NULL);
+  }
+}
+
+
+TEST_IMPL(timer_huge_repeat) {
+  ASSERT(0 == uv_timer_init(uv_default_loop(), &tiny_timer));
+  ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer1));
+  ASSERT(0 == uv_timer_start(&tiny_timer, huge_repeat_cb, 2, 2));
+  ASSERT(0 == uv_timer_start(&huge_timer1, huge_repeat_cb, 1, (uint64_t) -1));
+  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+  MAKE_VALGRIND_HAPPY();
   return 0;
 }
diff --git a/src/libuv/test/test-tty.c b/src/libuv/test/test-tty.c
index eb5d5df5..c26f7fa9 100644
--- a/src/libuv/test/test-tty.c
+++ b/src/libuv/test/test-tty.c
@@ -30,6 +30,9 @@
 # include <unistd.h>
 #endif
 
+#include <string.h>
+#include <errno.h>
+
 
 TEST_IMPL(tty) {
   int r, width, height;
@@ -62,7 +65,12 @@ TEST_IMPL(tty) {
 
 #else /* unix */
   ttyin_fd = open("/dev/tty", O_RDONLY, 0);
+  if (ttyin_fd < 0)
+    LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno));
+
   ttyout_fd = open("/dev/tty", O_WRONLY, 0);
+  if (ttyout_fd < 0)
+    LOGF("Cannot open /dev/tty as write-only: %s\n", strerror(errno));
 #endif
 
   ASSERT(ttyin_fd >= 0);
@@ -73,10 +81,10 @@ TEST_IMPL(tty) {
   ASSERT(UV_TTY == uv_guess_handle(ttyin_fd));
   ASSERT(UV_TTY == uv_guess_handle(ttyout_fd));
 
-  r = uv_tty_init(uv_default_loop(), &tty_in, ttyin_fd, 1);
+  r = uv_tty_init(uv_default_loop(), &tty_in, ttyin_fd, 1);  /* Readable. */
   ASSERT(r == 0);
 
-  r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 2);
+  r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 0);  /* Writable. */
   ASSERT(r == 0);
 
   r = uv_tty_get_winsize(&tty_out, &width, &height);
diff --git a/src/libuv/test/test-udp-send-and-recv.c b/src/libuv/test/test-udp-send-and-recv.c
index 37df5b62..1ffa6aa8 100644
--- a/src/libuv/test/test-udp-send-and-recv.c
+++ b/src/libuv/test/test-udp-send-and-recv.c
@@ -53,6 +53,7 @@ static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
 
 static void close_cb(uv_handle_t* handle) {
   CHECK_HANDLE(handle);
+  ASSERT(uv_is_closing(handle));
   close_cb_called++;
 }
 
diff --git a/src/libuv/uv.gyp b/src/libuv/uv.gyp
index 0810bcc4..f61ebb53 100644
--- a/src/libuv/uv.gyp
+++ b/src/libuv/uv.gyp
@@ -1,4 +1,13 @@
 {
+  'variables': {
+    'uv_use_dtrace%': 'false',
+    # uv_parent_path is the relative path to libuv in the parent project
+    # this is only relevant when dtrace is enabled and libuv is a child project
+    # as it's necessary to correctly locate the object files for post
+    # processing.
+    'uv_parent_path': '',
+  },
+
   'target_defaults': {
     'conditions': [
       ['OS != "win"', {
@@ -56,6 +65,7 @@
         'src/inet.c',
         'src/uv-common.c',
         'src/uv-common.h',
+        'src/version.c'
       ],
       'conditions': [
         [ 'OS=="win"', {
@@ -114,7 +124,6 @@
             '-pedantic',
             '-Wall',
             '-Wextra',
-            '-Wstrict-aliasing',
             '-Wno-unused-parameter',
           ],
           'sources': [
@@ -155,9 +164,16 @@
             ],
           },
           'conditions': [
-            ['"<(library)" == "shared_library"', {
+            ['library=="shared_library"', {
               'cflags': [ '-fPIC' ],
             }],
+            ['library=="shared_library" and OS!="mac"', {
+              'link_settings': {
+                # Must correspond with UV_VERSION_MAJOR and UV_VERSION_MINOR
+                # in src/version.c
+                'libraries': [ '-Wl,-soname,libuv.so.0.10' ],
+              },
+            }],
           ],
         }],
         [ 'OS=="linux" or OS=="mac"', {
@@ -167,7 +183,7 @@
           'sources': [
             'src/unix/darwin.c',
             'src/unix/fsevents.c',
-            'src/unix/darwin-proctitle.m',
+            'src/unix/darwin-proctitle.c',
           ],
           'link_settings': {
             'libraries': [
@@ -180,6 +196,11 @@
             '_DARWIN_USE_64_BIT_INODE=1',
           ]
         }],
+        [ 'OS!="mac"', {
+          # Enable on all platforms except OS X. The antique gcc/clang that
+          # ships with Xcode emits waaaay too many false positives.
+          'cflags': [ '-Wstrict-aliasing' ],
+        }],
         [ 'OS=="linux"', {
           'sources': [
             'src/unix/linux-core.c',
@@ -221,21 +242,16 @@
         }],
         [ 'OS=="freebsd" or OS=="dragonflybsd"', {
           'sources': [ 'src/unix/freebsd.c' ],
-          'link_settings': {
-            'libraries': [
-              '-lkvm',
-            ],
-          },
         }],
         [ 'OS=="openbsd"', {
           'sources': [ 'src/unix/openbsd.c' ],
         }],
         [ 'OS=="netbsd"', {
           'sources': [ 'src/unix/netbsd.c' ],
+        }],
+        [ 'OS in "freebsd dragonflybsd openbsd netbsd".split()', {
           'link_settings': {
-            'libraries': [
-              '-lkvm',
-            ],
+            'libraries': [ '-lkvm' ],
           },
         }],
         [ 'OS in "mac freebsd dragonflybsd openbsd netbsd".split()', {
@@ -243,7 +259,17 @@
         }],
         ['library=="shared_library"', {
           'defines': [ 'BUILDING_UV_SHARED=1' ]
-        }]
+        }],
+        ['uv_use_dtrace=="true"', {
+          'defines': [ 'HAVE_DTRACE=1' ],
+          'dependencies': [ 'uv_dtrace_header' ],
+          'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)' ],
+          'conditions': [
+            ['OS != "mac"', {
+              'sources': ['src/unix/dtrace.c' ],
+            }],
+          ],
+        }],
       ]
     },
 
@@ -285,6 +311,7 @@
         'test/test-loop-stop.c',
         'test/test-walk-handles.c',
         'test/test-multiple-listen.c',
+        'test/test-osx-select.c',
         'test/test-pass-always.c',
         'test/test-ping-pong.c',
         'test/test-pipe-bind-error.c',
@@ -326,6 +353,7 @@
         'test/test-barrier.c',
         'test/test-condvar.c',
         'test/test-timer-again.c',
+        'test/test-timer-from-check.c',
         'test/test-timer.c',
         'test/test-tty.c',
         'test/test-udp-dgram-too-big.c',
@@ -421,8 +449,48 @@
           'SubSystem': 1, # /subsystem:console
         },
       },
-    }
-  ]
-}
+    },
 
+    {
+      'target_name': 'uv_dtrace_header',
+      'type': 'none',
+      'conditions': [
+        [ 'uv_use_dtrace=="true"', {
+          'actions': [
+            {
+              'action_name': 'uv_dtrace_header',
+              'inputs': [ 'src/unix/uv-dtrace.d' ],
+              'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/uv-dtrace.h' ],
+              'action': [ 'dtrace', '-h', '-xnolibs', '-s', '<@(_inputs)',
+                '-o', '<@(_outputs)' ],
+            },
+          ],
+        }],
+      ],
+    },
 
+    {
+      'target_name': 'uv_dtrace_provider',
+      'type': 'none',
+      'conditions': [
+        [ 'uv_use_dtrace=="true" and OS!="mac"', {
+          'actions': [
+            {
+              'action_name': 'uv_dtrace_o',
+              'inputs': [
+                'src/unix/uv-dtrace.d',
+                '<(PRODUCT_DIR)/obj.target/libuv/<(uv_parent_path)/src/unix/core.o',
+              ],
+              'outputs': [
+                '<(PRODUCT_DIR)/obj.target/libuv/<(uv_parent_path)/src/unix/dtrace.o',
+              ],
+              'action': [ 'dtrace', '-G', '-xnolibs', '-s', '<@(_inputs)',
+                '-o', '<@(_outputs)' ]
+            }
+          ]
+        } ]
+      ]
+    },
+
+  ]
+}
diff --git a/src/libuv/vcbuild.bat b/src/libuv/vcbuild.bat
index 2165bda5..1b2f865a 100644
--- a/src/libuv/vcbuild.bat
+++ b/src/libuv/vcbuild.bat
@@ -41,6 +41,14 @@ shift
 goto next-arg
 :args-done
 
+@rem Look for Visual Studio 2012
+if not defined VS110COMNTOOLS goto vc-set-2010
+if not exist "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2010
+call "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset%
+set GYP_MSVS_VERSION=2012
+goto select-target
+
+:vc-set-2010
 @rem Look for Visual Studio 2010
 if not defined VS100COMNTOOLS goto vc-set-2008
 if not exist "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2008