summaryrefslogtreecommitdiff
path: root/deps/uv
diff options
context:
space:
mode:
authorTimothy J Fontaine <tjfontaine@gmail.com>2013-08-21 11:15:21 -0700
committerTimothy J Fontaine <tjfontaine@gmail.com>2013-08-21 11:15:21 -0700
commita784abaff631449533d44846987c1537c080e03d (patch)
tree0982d9a92450edb9e46ba683d75eb7822ea004b3 /deps/uv
parent41f55dc59b423b8b76e6f7971fd8f3a326a6fbad (diff)
downloadnodejs-a784abaff631449533d44846987c1537c080e03d.tar.gz
nodejs-a784abaff631449533d44846987c1537c080e03d.tar.bz2
nodejs-a784abaff631449533d44846987c1537c080e03d.zip
uv: Upgrade to v0.11.8
Diffstat (limited to 'deps/uv')
-rw-r--r--deps/uv/ChangeLog53
-rw-r--r--deps/uv/Makefile.am3
-rwxr-xr-xdeps/uv/autogen.sh31
-rw-r--r--deps/uv/configure.ac7
-rw-r--r--deps/uv/include/uv.h6
-rw-r--r--deps/uv/src/queue.h4
-rw-r--r--deps/uv/src/unix/async.c7
-rw-r--r--deps/uv/src/unix/darwin-proctitle.c29
-rw-r--r--deps/uv/src/unix/darwin.c139
-rw-r--r--deps/uv/src/unix/fs.c4
-rw-r--r--deps/uv/src/unix/fsevents.c267
-rw-r--r--deps/uv/src/unix/internal.h31
-rw-r--r--deps/uv/src/unix/kqueue.c1
-rw-r--r--deps/uv/src/unix/process.c4
-rw-r--r--deps/uv/src/unix/proctitle.c3
-rw-r--r--deps/uv/src/unix/signal.c2
-rw-r--r--deps/uv/src/unix/stream.c2
-rw-r--r--deps/uv/src/unix/threadpool.c5
-rw-r--r--deps/uv/src/uv-common.c10
-rw-r--r--deps/uv/src/uv-common.h10
-rw-r--r--deps/uv/src/version.c2
-rw-r--r--deps/uv/src/win/async.c6
-rw-r--r--deps/uv/src/win/internal.h5
-rw-r--r--deps/uv/src/win/tcp.c2
-rw-r--r--deps/uv/test/test-async-null-cb.c55
-rw-r--r--deps/uv/test/test-ip6-addr.c90
-rw-r--r--deps/uv/test/test-list.h2
-rw-r--r--deps/uv/uv.gyp1
28 files changed, 513 insertions, 268 deletions
diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog
index 8601b32f0..36b328313 100644
--- a/deps/uv/ChangeLog
+++ b/deps/uv/ChangeLog
@@ -1,4 +1,55 @@
-2013.08.07, Version 0.11.7 (Unstable)
+2013.08.22, Version 0.11.8 (Unstable)
+
+Changes since version 0.11.7:
+
+* unix: fix missing return value warning in stream.c (Ben Noordhuis)
+
+* build: serial-tests was added in automake v1.12 (Ben Noordhuis)
+
+* windows: fix uninitialized local variable warning (Ben Noordhuis)
+
+* windows: fix missing return value warning (Ben Noordhuis)
+
+* build: fix string comparisons in autogen.sh (Ben Noordhuis)
+
+* windows: move INLINE macro, remove UNUSED (Ben Noordhuis)
+
+* unix: clean up __attribute__((quux)) usage (Ben Noordhuis)
+
+* sunos: remove futimes() macro (Ben Noordhuis)
+
+* unix: fix uv__signal_unlock() prototype (Ben Noordhuis)
+
+* unix, windows: allow NULL async callback (Ben Noordhuis)
+
+* build: apply dtrace -G to all object files (Timothy J. Fontaine)
+
+* darwin: fix indentation in uv__hrtime() (Ben Noordhuis)
+
+* darwin: create fsevents thread on demand (Ben Noordhuis)
+
+* darwin: reduce fsevents thread stack size (Ben Noordhuis)
+
+* darwin: call pthread_setname_np() if available (Ben Noordhuis)
+
+* build: fix automake serial-tests check again (Ben Noordhuis)
+
+* unix: retry waitpid() on EINTR (Ben Noordhuis)
+
+* darwin: fix ios build error (Ben Noordhuis)
+
+* darwin: fix ios compiler warning (Ben Noordhuis)
+
+* test: simplify test-ip6-addr.c (Ben Noordhuis)
+
+* unix, windows: fix ipv6 link-local address parsing (Ben Noordhuis)
+
+* fsevents: FSEvents is most likely not thread-safe (Fedor Indutny)
+
+* windows: omit stdint.h, fix msvc 2008 build error (Ben Noordhuis)
+
+
+2013.08.07, Version 0.11.7 (Unstable), 3cad361f8776f70941b39d65bd9426bcb1aa817b
Changes since version 0.11.6:
diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am
index 8101110d5..e683f0057 100644
--- a/deps/uv/Makefile.am
+++ b/deps/uv/Makefile.am
@@ -63,6 +63,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/task.h \
test/test-active.c \
test/test-async.c \
+ test/test-async-null-cb.c \
test/test-barrier.c \
test/test-callback-order.c \
test/test-callback-stack.c \
@@ -215,7 +216,7 @@ src/unix/uv-dtrace.o: src/unix/uv-dtrace.d ${libuv_la_OBJECTS}
# every created .o, most projects don't need to include more than one .d
.d.o:
$(AM_V_GEN)$(DTRACE) $(DTRACEFLAGS) -G -o $(top_builddir)/uv-dtrace.o -s $< \
- `grep '^pic_object' $$(find ${top_builddir} -name "*.lo") | cut -f 2 -d\'`
+ `find ${top_builddir}/src -name "*.o"`
$(AM_V_GEN)printf %s\\n \
'# ${top_builddir}/uv-dtrace.lo - a libtool object file' \
'# Generated by libtool (GNU libtool) 2.4' \
diff --git a/deps/uv/autogen.sh b/deps/uv/autogen.sh
index ed07953e7..751b4f556 100755
--- a/deps/uv/autogen.sh
+++ b/deps/uv/autogen.sh
@@ -14,12 +14,33 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-if [ "$LIBTOOLIZE" == "" ] && [ "`uname`" == "Darwin" ]; then
+cd `dirname "$0"`
+
+if [ "$LIBTOOLIZE" = "" ] && [ "`uname`" = "Darwin" ]; then
LIBTOOLIZE=glibtoolize
fi
+ACLOCAL=${ACLOCAL:-aclocal}
+AUTOCONF=${AUTOCONF:-autoconf}
+AUTOMAKE=${AUTOMAKE:-automake}
+LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
+
+automake_version=`"$AUTOMAKE" --version | head -n 1 | sed 's/[^.0-9]//g'`
+automake_version_major=`echo "$automake_version" | cut -d. -f1`
+automake_version_minor=`echo "$automake_version" | cut -d. -f2`
+
+UV_EXTRA_AUTOMAKE_FLAGS=
+if test "$automake_version_major" -gt 1 || \
+ test "$automake_version_major" -eq 1 && \
+ test "$automake_version_minor" -gt 11; then
+ # serial-tests is available in v0.12 and newer.
+ UV_EXTRA_AUTOMAKE_FLAGS="$UV_EXTRA_AUTOMAKE_FLAGS serial-tests"
+fi
+echo "m4_define([UV_EXTRA_AUTOMAKE_FLAGS], [$UV_EXTRA_AUTOMAKE_FLAGS])" \
+ > m4/libuv-extra-automake-flags.m4
+
set -ex
-${LIBTOOLIZE:-libtoolize}
-${ACLOCAL:-aclocal -I m4}
-${AUTOCONF:-autoconf}
-${AUTOMAKE:-automake} --add-missing
+"$LIBTOOLIZE"
+"$ACLOCAL" -I m4
+"$AUTOCONF"
+"$AUTOMAKE" --add-missing --copy
diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac
index f50e63536..d9760a32e 100644
--- a/deps/uv/configure.ac
+++ b/deps/uv/configure.ac
@@ -14,12 +14,9 @@
AC_PREREQ(2.57)
AC_INIT([libuv], [0.11.5], [https://github.com/joyent/libuv/issues])
-# Use AM_SILENT_RULES as an ad-hoc version check to find out if it's safe
-# to use the serial-tests directive. Both were added in automake v0.11.
-AM_INIT_AUTOMAKE(m4_ifdef([AM_SILENT_RULES],
- [-Wall -Werror foreign subdir-objects serial-tests],
- [-Wall -Werror foreign subdir-objects]))
AC_CONFIG_MACRO_DIR([m4])
+m4_include([m4/libuv-extra-automake-flags.m4])
+AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS)
AC_CANONICAL_HOST
AC_ENABLE_SHARED
AC_ENABLE_STATIC
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index 5c993b451..5821cce8a 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -1239,6 +1239,12 @@ struct uv_async_s {
UV_ASYNC_PRIVATE_FIELDS
};
+/*
+ * Initialize the uv_async_t handle. A NULL callback is allowed.
+ *
+ * Note that uv_async_init(), unlike other libuv functions, immediately
+ * starts the handle. To stop the handle again, close it with uv_close().
+ */
UV_EXTERN int uv_async_init(uv_loop_t*, uv_async_t* async,
uv_async_cb async_cb);
diff --git a/deps/uv/src/queue.h b/deps/uv/src/queue.h
index 2f5ab6100..aa15837d0 100644
--- a/deps/uv/src/queue.h
+++ b/deps/uv/src/queue.h
@@ -16,8 +16,6 @@
#ifndef QUEUE_H_
#define QUEUE_H_
-#include <stdint.h>
-
typedef void *QUEUE[2];
/* Private macros. */
@@ -28,7 +26,7 @@ typedef void *QUEUE[2];
/* Public macros. */
#define QUEUE_DATA(ptr, type, field) \
- ((type *) ((char *) (ptr) - ((uintptr_t) &((type *) 0)->field)))
+ ((type *) ((char *) (ptr) - ((char *) &((type *) 0)->field)))
#define QUEUE_FOREACH(q, h) \
for ((q) = (QUEUE *) (*(h))[0]; (q) != (h); (q) = (QUEUE *) (*(q))[0])
diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c
index f526ba3eb..5ced3cbe0 100644
--- a/deps/uv/src/unix/async.c
+++ b/deps/uv/src/unix/async.c
@@ -78,8 +78,13 @@ static void uv__async_event(uv_loop_t* loop,
QUEUE_FOREACH(q, &loop->async_handles) {
h = QUEUE_DATA(q, uv_async_t, queue);
- if (!h->pending) continue;
+
+ if (h->pending == 0)
+ continue;
h->pending = 0;
+
+ if (h->async_cb == NULL)
+ continue;
h->async_cb(h, 0);
}
}
diff --git a/deps/uv/src/unix/darwin-proctitle.c b/deps/uv/src/unix/darwin-proctitle.c
index 56c141766..90b2e4188 100644
--- a/deps/uv/src/unix/darwin-proctitle.c
+++ b/deps/uv/src/unix/darwin-proctitle.c
@@ -18,6 +18,10 @@
* IN THE SOFTWARE.
*/
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdlib.h>
+
#include <TargetConditionals.h>
#if !TARGET_OS_IPHONE
@@ -26,9 +30,30 @@
#endif
+static int uv__pthread_setname_np(const char* name) {
+ int (*dynamic_pthread_setname_np)(const char* name);
+ char namebuf[64]; /* MAXTHREADNAMESIZE */
+ int err;
+
+ /* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */
+ dynamic_pthread_setname_np = dlsym(RTLD_DEFAULT, "pthread_setname_np");
+ if (dynamic_pthread_setname_np == NULL)
+ return -ENOSYS;
+
+ strncpy(namebuf, name, sizeof(namebuf) - 1);
+ namebuf[sizeof(namebuf) - 1] = '\0';
+
+ err = dynamic_pthread_setname_np(namebuf);
+ if (err)
+ return -err;
+
+ return 0;
+}
+
+
int uv__set_process_title(const char* title) {
#if TARGET_OS_IPHONE
- return -ENOSYS;
+ return uv__pthread_setname_np(title);
#else
typedef CFTypeRef (*LSGetCurrentApplicationASNType)(void);
typedef OSStatus (*LSSetApplicationInformationItemType)(int,
@@ -84,6 +109,8 @@ int uv__set_process_title(const char* title) {
if (err != noErr)
return -ENOENT;
+ uv__pthread_setname_np(title); /* Don't care if it fails. */
+
return 0;
#endif /* !TARGET_OS_IPHONE */
}
diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c
index 81570f398..8a9b4bab6 100644
--- a/deps/uv/src/unix/darwin.c
+++ b/deps/uv/src/unix/darwin.c
@@ -29,8 +29,6 @@
#include <net/if.h>
#include <net/if_dl.h>
-#include <CoreFoundation/CFRunLoop.h>
-
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <mach-o/dyld.h> /* _NSGetExecutablePath */
@@ -38,154 +36,29 @@
#include <sys/sysctl.h>
#include <unistd.h> /* sysconf */
-/* Forward declarations */
-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 {
- void* arg;
- cf_loop_signal_cb cb;
- QUEUE member;
-};
-
int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
- CFRunLoopSourceContext ctx;
- int r;
+ loop->cf_loop = NULL;
if (uv__kqueue_init(loop))
return -errno;
- loop->cf_loop = NULL;
- if ((r = uv_mutex_init(&loop->cf_mutex)))
- return r;
- if ((r = uv_sem_init(&loop->cf_sem, 0)))
- return r;
- QUEUE_INIT(&loop->cf_signals);
-
- memset(&ctx, 0, sizeof(ctx));
- ctx.info = loop;
- ctx.perform = uv__cf_loop_cb;
- loop->cf_cb = CFRunLoopSourceCreate(NULL, 0, &ctx);
-
- if ((r = uv_thread_create(&loop->cf_thread, uv__cf_loop_runner, loop)))
- return r;
-
- /* Synchronize threads */
- uv_sem_wait(&loop->cf_sem);
- assert(ACCESS_ONCE(CFRunLoopRef, loop->cf_loop) != NULL);
-
return 0;
}
void uv__platform_loop_delete(uv_loop_t* loop) {
- QUEUE* item;
- uv__cf_loop_signal_t* s;
-
- assert(loop->cf_loop != NULL);
- uv__cf_loop_signal(loop, NULL, NULL);
- uv_thread_join(&loop->cf_thread);
-
- uv_sem_destroy(&loop->cf_sem);
- uv_mutex_destroy(&loop->cf_mutex);
-
- /* Free any remaining data */
- while (!QUEUE_EMPTY(&loop->cf_signals)) {
- item = QUEUE_HEAD(&loop->cf_signals);
-
- s = QUEUE_DATA(item, uv__cf_loop_signal_t, member);
-
- QUEUE_REMOVE(item);
- free(s);
- }
-}
-
-
-static void uv__cf_loop_runner(void* arg) {
- uv_loop_t* loop;
-
- loop = arg;
-
- /* Get thread's loop */
- ACCESS_ONCE(CFRunLoopRef, loop->cf_loop) = CFRunLoopGetCurrent();
-
- CFRunLoopAddSource(loop->cf_loop,
- loop->cf_cb,
- kCFRunLoopDefaultMode);
-
- uv_sem_post(&loop->cf_sem);
-
- CFRunLoopRun();
-
- CFRunLoopRemoveSource(loop->cf_loop,
- loop->cf_cb,
- kCFRunLoopDefaultMode);
-}
-
-
-static void uv__cf_loop_cb(void* arg) {
- uv_loop_t* loop;
- QUEUE* item;
- QUEUE split_head;
- uv__cf_loop_signal_t* s;
-
- loop = arg;
-
- uv_mutex_lock(&loop->cf_mutex);
- QUEUE_INIT(&split_head);
- if (!QUEUE_EMPTY(&loop->cf_signals)) {
- QUEUE* split_pos = QUEUE_HEAD(&loop->cf_signals);
- QUEUE_SPLIT(&loop->cf_signals, split_pos, &split_head);
- }
- uv_mutex_unlock(&loop->cf_mutex);
-
- while (!QUEUE_EMPTY(&split_head)) {
- item = QUEUE_HEAD(&split_head);
-
- s = QUEUE_DATA(item, uv__cf_loop_signal_t, member);
-
- /* This was a termination signal */
- if (s->cb == NULL)
- CFRunLoopStop(loop->cf_loop);
- else
- s->cb(s->arg);
-
- QUEUE_REMOVE(item);
- free(s);
- }
-}
-
-
-void uv__cf_loop_signal(uv_loop_t* loop, cf_loop_signal_cb cb, void* arg) {
- uv__cf_loop_signal_t* item;
-
- item = malloc(sizeof(*item));
- /* XXX: Fail */
- if (item == NULL)
- abort();
-
- item->arg = arg;
- item->cb = cb;
-
- uv_mutex_lock(&loop->cf_mutex);
- QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member);
- uv_mutex_unlock(&loop->cf_mutex);
-
- assert(loop->cf_loop != NULL);
- CFRunLoopSourceSignal(loop->cf_cb);
- CFRunLoopWakeUp(loop->cf_loop);
+ uv__fsevents_loop_delete(loop);
}
uint64_t uv__hrtime(void) {
- mach_timebase_info_data_t info;
+ mach_timebase_info_data_t info;
- if (mach_timebase_info(&info) != KERN_SUCCESS)
- abort();
+ if (mach_timebase_info(&info) != KERN_SUCCESS)
+ abort();
- return mach_absolute_time() * info.numer / info.denom;
+ return mach_absolute_time() * info.numer / info.denom;
}
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index ecd2b239d..6cabf5137 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -176,7 +176,11 @@ skip:
tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000;
tv[1].tv_sec = req->mtime;
tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000;
+# if defined(__sun)
+ return futimesat(req->file, NULL, tv);
+# else
return futimes(req->file, tv);
+# endif
#else
errno = ENOSYS;
return -1;
diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c
index ef9a352b7..79ad198ba 100644
--- a/deps/uv/src/unix/fsevents.c
+++ b/deps/uv/src/unix/fsevents.c
@@ -34,13 +34,28 @@ int uv__fsevents_close(uv_fs_event_t* handle) {
return 0;
}
+
+void uv__fsevents_loop_delete(uv_loop_t* loop) {
+}
+
#else /* TARGET_OS_IPHONE */
#include <assert.h>
#include <stdlib.h>
+#include <pthread.h>
+
+#include <CoreFoundation/CFRunLoop.h>
#include <CoreServices/CoreServices.h>
typedef struct uv__fsevents_event_s uv__fsevents_event_t;
+typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t;
+typedef void (*cf_loop_signal_cb)(void* arg);
+
+struct uv__cf_loop_signal_s {
+ cf_loop_signal_cb cb;
+ QUEUE member;
+ void* arg;
+};
struct uv__fsevents_event_s {
int events;
@@ -48,6 +63,12 @@ struct uv__fsevents_event_s {
char path[1];
};
+/* Forward declarations */
+static void uv__cf_loop_cb(void* arg);
+static void* uv__cf_loop_runner(void* arg);
+static void uv__cf_loop_signal(uv_loop_t* loop,
+ cf_loop_signal_cb cb,
+ void* arg);
#define UV__FSEVENTS_WALK(handle, block) \
{ \
@@ -75,7 +96,7 @@ struct uv__fsevents_event_s {
}
-void uv__fsevents_cb(uv_async_t* cb, int status) {
+static void uv__fsevents_cb(uv_async_t* cb, int status) {
uv_fs_event_t* handle;
handle = cb->data;
@@ -92,12 +113,12 @@ void uv__fsevents_cb(uv_async_t* cb, int status) {
}
-void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
- void* info,
- size_t numEvents,
- void* eventPaths,
- const FSEventStreamEventFlags eventFlags[],
- const FSEventStreamEventId eventIds[]) {
+static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
+ void* info,
+ size_t numEvents,
+ void* eventPaths,
+ const FSEventStreamEventFlags eventFlags[],
+ const FSEventStreamEventId eventIds[]) {
size_t i;
int len;
char** paths;
@@ -190,19 +211,8 @@ void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
}
-void uv__fsevents_schedule(void* arg) {
+static void uv__fsevents_schedule(void* arg) {
uv_fs_event_t* handle;
-
- handle = arg;
- FSEventStreamScheduleWithRunLoop(handle->cf_eventstream,
- handle->loop->cf_loop,
- kCFRunLoopDefaultMode);
- FSEventStreamStart(handle->cf_eventstream);
- uv_sem_post(&handle->cf_sem);
-}
-
-
-int uv__fsevents_init(uv_fs_event_t* handle) {
FSEventStreamContext ctx;
FSEventStreamRef ref;
CFStringRef path;
@@ -210,6 +220,8 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
CFAbsoluteTime latency;
FSEventStreamCreateFlags flags;
+ handle = arg;
+
/* Initialize context */
ctx.version = 0;
ctx.info = handle;
@@ -217,16 +229,13 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
ctx.release = NULL;
ctx.copyDescription = NULL;
- /* Get absolute path to file */
- handle->realpath = realpath(handle->filename, NULL);
- if (handle->realpath != NULL)
- handle->realpath_len = strlen(handle->realpath);
-
/* Initialize paths array */
path = CFStringCreateWithCString(NULL,
handle->filename,
CFStringGetSystemEncoding());
+ assert(path != NULL);
paths = CFArrayCreate(NULL, (const void**)&path, 1, NULL);
+ assert(paths != NULL);
latency = 0.15;
@@ -240,8 +249,203 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
kFSEventStreamEventIdSinceNow,
latency,
flags);
+ assert(ref != NULL);
handle->cf_eventstream = ref;
+ FSEventStreamScheduleWithRunLoop(handle->cf_eventstream,
+ handle->loop->cf_loop,
+ kCFRunLoopDefaultMode);
+ if (!FSEventStreamStart(handle->cf_eventstream))
+ abort();
+}
+
+
+static void uv__fsevents_unschedule(void* arg) {
+ uv_fs_event_t* handle;
+
+ handle = arg;
+
+ /* Stop emitting events */
+ FSEventStreamStop(handle->cf_eventstream);
+
+ /* Release stream */
+ FSEventStreamInvalidate(handle->cf_eventstream);
+ FSEventStreamRelease(handle->cf_eventstream);
+ handle->cf_eventstream = NULL;
+
+ /* Notify main thread that we're done here */
+ uv_sem_post(&handle->cf_sem);
+}
+
+
+static int uv__fsevents_loop_init(uv_loop_t* loop) {
+ CFRunLoopSourceContext ctx;
+ pthread_attr_t attr_storage;
+ pthread_attr_t* attr;
+ int err;
+
+ if (loop->cf_loop != NULL)
+ return 0;
+
+ err = uv_mutex_init(&loop->cf_mutex);
+ if (err)
+ return err;
+
+ err = uv_sem_init(&loop->cf_sem, 0);
+ if (err)
+ goto fail_sem_init;
+
+ QUEUE_INIT(&loop->cf_signals);
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.info = loop;
+ ctx.perform = uv__cf_loop_cb;
+ loop->cf_cb = CFRunLoopSourceCreate(NULL, 0, &ctx);
+
+ /* In the unlikely event that pthread_attr_init() fails, create the thread
+ * with the default stack size. We'll use a little more address space but
+ * that in itself is not a fatal error.
+ */
+ attr = &attr_storage;
+ if (pthread_attr_init(attr))
+ attr = NULL;
+
+ if (attr != NULL)
+ if (pthread_attr_setstacksize(attr, 3 * PTHREAD_STACK_MIN))
+ abort();
+
+ /* uv_thread_t is an alias for pthread_t. */
+ err = -pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop);
+
+ if (attr != NULL)
+ pthread_attr_destroy(attr);
+
+ if (err)
+ goto fail_thread_create;
+
+ /* Synchronize threads */
+ uv_sem_wait(&loop->cf_sem);
+ assert(loop->cf_loop != NULL);
+ return 0;
+
+fail_thread_create:
+ uv_sem_destroy(&loop->cf_sem);
+
+fail_sem_init:
+ uv_mutex_destroy(&loop->cf_mutex);
+ return err;
+}
+
+
+void uv__fsevents_loop_delete(uv_loop_t* loop) {
+ uv__cf_loop_signal_t* s;
+ QUEUE* q;
+
+ if (loop->cf_loop == NULL)
+ return;
+
+ uv__cf_loop_signal(loop, NULL, NULL);
+ uv_thread_join(&loop->cf_thread);
+ uv_sem_destroy(&loop->cf_sem);
+ uv_mutex_destroy(&loop->cf_mutex);
+
+ /* Free any remaining data */
+ while (!QUEUE_EMPTY(&loop->cf_signals)) {
+ q = QUEUE_HEAD(&loop->cf_signals);
+ s = QUEUE_DATA(q, uv__cf_loop_signal_t, member);
+ QUEUE_REMOVE(q);
+ free(s);
+ }
+}
+
+
+static void* uv__cf_loop_runner(void* arg) {
+ uv_loop_t* loop;
+
+ loop = arg;
+ loop->cf_loop = CFRunLoopGetCurrent();
+
+ CFRunLoopAddSource(loop->cf_loop,
+ loop->cf_cb,
+ kCFRunLoopDefaultMode);
+
+ uv_sem_post(&loop->cf_sem);
+
+ CFRunLoopRun();
+ CFRunLoopRemoveSource(loop->cf_loop,
+ loop->cf_cb,
+ kCFRunLoopDefaultMode);
+
+ return NULL;
+}
+
+
+static void uv__cf_loop_cb(void* arg) {
+ uv_loop_t* loop;
+ QUEUE* item;
+ QUEUE split_head;
+ uv__cf_loop_signal_t* s;
+
+ loop = arg;
+
+ uv_mutex_lock(&loop->cf_mutex);
+ QUEUE_INIT(&split_head);
+ if (!QUEUE_EMPTY(&loop->cf_signals)) {
+ QUEUE* split_pos = QUEUE_HEAD(&loop->cf_signals);
+ QUEUE_SPLIT(&loop->cf_signals, split_pos, &split_head);
+ }
+ uv_mutex_unlock(&loop->cf_mutex);
+
+ while (!QUEUE_EMPTY(&split_head)) {
+ item = QUEUE_HEAD(&split_head);
+
+ s = QUEUE_DATA(item, uv__cf_loop_signal_t, member);
+
+ /* This was a termination signal */
+ if (s->cb == NULL)
+ CFRunLoopStop(loop->cf_loop);
+ else
+ s->cb(s->arg);
+
+ QUEUE_REMOVE(item);
+ free(s);
+ }
+}
+
+
+void uv__cf_loop_signal(uv_loop_t* loop, cf_loop_signal_cb cb, void* arg) {
+ uv__cf_loop_signal_t* item;
+
+ item = malloc(sizeof(*item));
+ /* XXX: Fail */
+ if (item == NULL)
+ abort();
+
+ item->arg = arg;
+ item->cb = cb;
+
+ uv_mutex_lock(&loop->cf_mutex);
+ QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member);
+ uv_mutex_unlock(&loop->cf_mutex);
+
+ assert(loop->cf_loop != NULL);
+ CFRunLoopSourceSignal(loop->cf_cb);
+ CFRunLoopWakeUp(loop->cf_loop);
+}
+
+
+int uv__fsevents_init(uv_fs_event_t* handle) {
+ int err;
+
+ err = uv__fsevents_loop_init(handle->loop);
+ if (err)
+ return err;
+
+ /* Get absolute path to file */
+ handle->realpath = realpath(handle->filename, NULL);
+ if (handle->realpath != NULL)
+ handle->realpath_len = strlen(handle->realpath);
+
+ handle->cf_eventstream = NULL;
/*
* Events will occur in other thread.
* Initialize callback for getting them back into event loop's thread
@@ -266,21 +470,16 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
int uv__fsevents_close(uv_fs_event_t* handle) {
- if (handle->cf_eventstream == NULL)
+ if (handle->cf_cb == NULL)
return -EINVAL;
- /* Ensure that event stream was scheduled */
- uv_sem_wait(&handle->cf_sem);
-
- /* Stop emitting events */
- FSEventStreamStop(handle->cf_eventstream);
+ uv__cf_loop_signal(handle->loop, uv__fsevents_unschedule, handle);
- /* Release stream */
- FSEventStreamInvalidate(handle->cf_eventstream);
- FSEventStreamRelease(handle->cf_eventstream);
- handle->cf_eventstream = NULL;
+ /* Wait for deinitialization */
+ uv_sem_wait(&handle->cf_sem);
uv_close((uv_handle_t*) handle->cf_cb, (uv_close_cb) free);
+ handle->cf_cb = NULL;
/* Free data in queue */
UV__FSEVENTS_WALK(handle, {
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 2c4e3e918..8559e3318 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -39,7 +39,6 @@
#if defined(__sun)
# include <sys/port.h>
# include <port.h>
-# define futimes(fd, tv) futimesat(fd, (void*)0, tv)
#endif /* __sun */
#if defined(__APPLE__) && !TARGET_OS_IPHONE
@@ -67,6 +66,21 @@
} \
while (0)
+/* The __clang__ and __INTEL_COMPILER checks are superfluous because they
+ * define __GNUC__. They are here to convey to you, dear reader, that these
+ * macros are enabled when compiling with clang or icc.
+ */
+#if defined(__clang__) || \
+ defined(__GNUC__) || \
+ defined(__INTEL_COMPILER) || \
+ defined(__SUNPRO_C)
+# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration
+# define UV_UNUSED(declaration) __attribute__((unused)) declaration
+#else
+# define UV_DESTRUCTOR(declaration) declaration
+# define UV_UNUSED(declaration) declaration
+#endif
+
#if defined(__linux__)
# define UV__POLLIN UV__EPOLLIN
# define UV__POLLOUT UV__EPOLLOUT
@@ -215,12 +229,10 @@ int uv__make_socketpair(int fds[2], int flags);
int uv__make_pipe(int fds[2], int flags);
#if defined(__APPLE__)
-typedef void (*cf_loop_signal_cb)(void*);
-
-void uv__cf_loop_signal(uv_loop_t* loop, cf_loop_signal_cb cb, void* arg);
int uv__fsevents_init(uv_fs_event_t* handle);
int uv__fsevents_close(uv_fs_event_t* handle);
+void uv__fsevents_loop_delete(uv_loop_t* loop);
/* OSX < 10.7 has no file events, polyfill them */
#ifndef MAC_OS_X_VERSION_10_7
@@ -242,21 +254,20 @@ static const int kFSEventStreamEventFlagItemIsSymlink = 0x00040000;
#endif /* defined(__APPLE__) */
-__attribute__((unused))
-static void uv__req_init(uv_loop_t* loop, uv_req_t* req, uv_req_type type) {
+UV_UNUSED(static void uv__req_init(uv_loop_t* loop,
+ uv_req_t* req,
+ uv_req_type type)) {
req->type = type;
uv__req_register(loop, req);
}
#define uv__req_init(loop, req, type) \
uv__req_init((loop), (uv_req_t*)(req), (type))
-__attribute__((unused))
-static void uv__update_time(uv_loop_t* loop) {
+UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) {
loop->time = uv__hrtime() / 1000000;
}
-__attribute__((unused))
-static char* uv__basename_r(const char* path) {
+UV_UNUSED(static char* uv__basename_r(const char* path)) {
char* s;
s = strrchr(path, '/');
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index f23391f6f..2c68bf36f 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -319,6 +319,7 @@ int uv_fs_event_init(uv_loop_t* loop,
#if defined(__APPLE__)
/* Nullify field to perform checks later */
+ handle->cf_cb = NULL;
handle->cf_eventstream = NULL;
handle->realpath = NULL;
handle->realpath_len = 0;
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
index c37bb3efd..a9ecb4548 100644
--- a/deps/uv/src/unix/process.c
+++ b/deps/uv/src/unix/process.c
@@ -73,7 +73,9 @@ static void uv__chld(uv_signal_t* handle, int signum) {
assert(signum == SIGCHLD);
for (;;) {
- pid = waitpid(-1, &status, WNOHANG);
+ do
+ pid = waitpid(-1, &status, WNOHANG);
+ while (pid == -1 && errno == EINTR);
if (pid == 0)
return;
diff --git a/deps/uv/src/unix/proctitle.c b/deps/uv/src/unix/proctitle.c
index 8ffebb141..16b052373 100644
--- a/deps/uv/src/unix/proctitle.c
+++ b/deps/uv/src/unix/proctitle.c
@@ -96,8 +96,7 @@ int uv_get_process_title(char* buffer, size_t size) {
}
-__attribute__((destructor))
-static void free_args_mem(void) {
+UV_DESTRUCTOR(static void free_args_mem(void)) {
free(args_mem); /* Keep valgrind happy. */
args_mem = NULL;
}
diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c
index 583909867..53e524a34 100644
--- a/deps/uv/src/unix/signal.c
+++ b/deps/uv/src/unix/signal.c
@@ -37,7 +37,7 @@ typedef struct {
RB_HEAD(uv__signal_tree_s, uv_signal_s);
-static int uv__signal_unlock();
+static int uv__signal_unlock(void);
static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events);
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2);
static void uv__signal_stop(uv_signal_t* handle);
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 6d1144f6b..5f42c3443 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -1443,4 +1443,6 @@ void uv__stream_close(uv_stream_t* handle) {
int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {
assert(0 && "implement me");
+ abort();
+ return 0;
}
diff --git a/deps/uv/src/unix/threadpool.c b/deps/uv/src/unix/threadpool.c
index 5a3a5f5b6..7923250a0 100644
--- a/deps/uv/src/unix/threadpool.c
+++ b/deps/uv/src/unix/threadpool.c
@@ -129,9 +129,7 @@ static void init_once(void) {
}
-#if defined(__GNUC__)
-__attribute__((destructor))
-static void cleanup(void) {
+UV_DESTRUCTOR(static void cleanup(void)) {
unsigned int i;
if (initialized == 0)
@@ -153,7 +151,6 @@ static void cleanup(void) {
nthreads = 0;
initialized = 0;
}
-#endif
void uv__work_submit(uv_loop_t* loop,
diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c
index 532f53fc4..95f5011f1 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -154,11 +154,12 @@ struct sockaddr_in6 uv_ip6_addr(const char* ip, int port) {
#if defined(UV_PLATFORM_HAS_IP6_LINK_LOCAL_ADDRESS)
zone_index = strchr(ip, '%');
if (zone_index != NULL) {
- address_part_size = sizeof(address_part);
- assert((unsigned)(zone_index - ip) < address_part_size);
- strncpy(address_part, ip, zone_index - ip);
- address_part[address_part_size - 1] = '\0';
+ address_part_size = zone_index - ip;
+ if (address_part_size >= sizeof(address_part))
+ address_part_size = sizeof(address_part) - 1;
+ memcpy(address_part, ip, address_part_size);
+ address_part[address_part_size] = '\0';
ip = address_part;
zone_index++; /* skip '%' */
@@ -473,4 +474,5 @@ int uv__getaddrinfo_translate_error(int sys_err) {
}
assert(!"unknown EAI_* error code");
abort();
+ return 0; /* Pacify compiler. */
}
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
index f3d736817..dc1509123 100644
--- a/deps/uv/src/uv-common.h
+++ b/deps/uv/src/uv-common.h
@@ -40,21 +40,11 @@
#include "tree.h"
#include "queue.h"
-
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define container_of(ptr, type, member) \
((type *) ((char *) (ptr) - offsetof(type, member)))
-#ifdef _MSC_VER
-# define UNUSED /* empty */
-# define INLINE __inline
-#else
-# define UNUSED __attribute__((unused))
-# define INLINE inline
-#endif
-
-
#ifndef _WIN32
enum {
UV__HANDLE_INTERNAL = 0x8000,
diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c
index e18cf15ba..e0a621f58 100644
--- a/deps/uv/src/version.c
+++ b/deps/uv/src/version.c
@@ -31,7 +31,7 @@
#define UV_VERSION_MAJOR 0
#define UV_VERSION_MINOR 11
-#define UV_VERSION_PATCH 7
+#define UV_VERSION_PATCH 8
#define UV_VERSION_IS_RELEASE 1
diff --git a/deps/uv/src/win/async.c b/deps/uv/src/win/async.c
index edf652973..e192ead90 100644
--- a/deps/uv/src/win/async.c
+++ b/deps/uv/src/win/async.c
@@ -91,9 +91,9 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
handle->async_sent = 0;
- if (!(handle->flags & UV__HANDLE_CLOSING)) {
- handle->async_cb((uv_async_t*) handle, 0);
- } else {
+ if (handle->flags & UV__HANDLE_CLOSING) {
uv_want_endgame(loop, (uv_handle_t*)handle);
+ } else if (handle->async_cb != NULL) {
+ handle->async_cb(handle, 0);
}
}
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index 7eaf41045..98c96a7c2 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -29,6 +29,11 @@
#include "winapi.h"
#include "winsock.h"
+#ifdef _MSC_VER
+# define INLINE __inline
+#else
+# define INLINE inline
+#endif
/*
* Handles
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index 87787149e..5ed7976c0 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -436,7 +436,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
handle->flags &= ~UV_HANDLE_ZERO_READ;
handle->read_buffer = handle->alloc_cb((uv_handle_t*) handle, 65536);
if (handle->read_buffer.len == 0) {
- handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, buf);
+ handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, handle->read_buffer);
return;
}
assert(handle->read_buffer.base != NULL);
diff --git a/deps/uv/test/test-async-null-cb.c b/deps/uv/test/test-async-null-cb.c
new file mode 100644
index 000000000..d65488426
--- /dev/null
+++ b/deps/uv/test/test-async-null-cb.c
@@ -0,0 +1,55 @@
+/* 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_async_t async_handle;
+static uv_check_t check_handle;
+static int check_cb_called;
+static uv_thread_t thread;
+
+
+static void thread_cb(void* dummy) {
+ (void) &dummy;
+ uv_async_send(&async_handle);
+}
+
+
+static void check_cb(uv_check_t* handle, int status) {
+ ASSERT(check_cb_called == 0);
+ uv_close((uv_handle_t*) &async_handle, NULL);
+ uv_close((uv_handle_t*) &check_handle, NULL);
+ check_cb_called++;
+}
+
+
+TEST_IMPL(async_null_cb) {
+ ASSERT(0 == uv_async_init(uv_default_loop(), &async_handle, NULL));
+ ASSERT(0 == uv_check_init(uv_default_loop(), &check_handle));
+ ASSERT(0 == uv_check_start(&check_handle, check_cb));
+ ASSERT(0 == uv_thread_create(&thread, thread_cb, NULL));
+ ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+ ASSERT(0 == uv_thread_join(&thread));
+ ASSERT(1 == check_cb_called);
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-ip6-addr.c b/deps/uv/test/test-ip6-addr.c
index 9cd9b97cf..91891bffb 100644
--- a/deps/uv/test/test-ip6-addr.c
+++ b/deps/uv/test/test-ip6-addr.c
@@ -30,72 +30,68 @@
# include <net/if.h>
#endif
-typedef void (*iface_info_cb)(const char* ip6_addr, const char* device_name,
- unsigned iface_index);
-void call_iface_info_cb(iface_info_cb iface_cb,
- char const* iface_name,
- struct sockaddr_in6 const* address) {
+TEST_IMPL(ip6_addr_link_local) {
+#ifdef UV_PLATFORM_HAS_IP6_LINK_LOCAL_ADDRESS
char string_address[INET6_ADDRSTRLEN];
-
- ASSERT(0 == uv_inet_ntop(AF_INET6,
- &address->sin6_addr,
- string_address,
- INET6_ADDRSTRLEN));
- iface_cb(string_address, iface_name, address->sin6_scope_id);
-}
-
-
-void foreach_ip6_interface(iface_info_cb iface_cb) {
- int count, ix;
uv_interface_address_t* addresses;
+ uv_interface_address_t* address;
+ struct sockaddr_in6 addr;
+ unsigned int iface_index;
+ const char* device_name;
+ /* 40 bytes address, 16 bytes device name, plus reserve. */
+ char scoped_addr[128];
+ int count;
+ int ix;
ASSERT(0 == uv_interface_addresses(&addresses, &count));
for (ix = 0; ix < count; ix++) {
- if (addresses[ix].address.address4.sin_family != AF_INET6)
- continue;
+ address = addresses + ix;
- call_iface_info_cb(iface_cb,
- addresses[ix].name,
- &addresses[ix].address.address6);
- }
-
- uv_free_interface_addresses(addresses, count);
-}
+ if (address->address.address6.sin6_family != AF_INET6)
+ continue;
+ ASSERT(0 == uv_inet_ntop(AF_INET6,
+ &address->address.address6.sin6_addr,
+ string_address,
+ sizeof(string_address)));
-void test_ip6_addr_scope(const char* ip6_addr,
- const char* device_name,
- unsigned iface_index) {
- /* 40 bytes address, 16 bytes device name, plus reserve */
- char scoped_addr[128];
- struct sockaddr_in6 addr;
+ /* Skip addresses that are not link-local. */
+ if (strncmp(string_address, "fe80::", 6) != 0)
+ continue;
- /* skip addresses that are not link-local */
- if (strncmp(ip6_addr, "fe80::", 6) != 0) return;
+ iface_index = address->address.address6.sin6_scope_id;
+ device_name = address->name;
#ifdef _WIN32
- snprintf(scoped_addr, sizeof(scoped_addr), "%s%%%d", ip6_addr, iface_index);
+ snprintf(scoped_addr,
+ sizeof(scoped_addr),
+ "%s%%%d",
+ string_address,
+ iface_index);
#else
- snprintf(scoped_addr, sizeof(scoped_addr), "%s%%%s", ip6_addr, device_name);
+ snprintf(scoped_addr,
+ sizeof(scoped_addr),
+ "%s%%%s",
+ string_address,
+ device_name);
#endif
- LOGF("Testing link-local address %s (iface_index: 0x%02x, device_name: %s)\n",
- scoped_addr,
- iface_index,
- device_name);
-
- addr = uv_ip6_addr(scoped_addr, TEST_PORT);
+ LOGF("Testing link-local address %s "
+ "(iface_index: 0x%02x, device_name: %s)\n",
+ scoped_addr,
+ iface_index,
+ device_name);
- LOGF("Got scope_id 0x%02x\n", addr.sin6_scope_id);
- ASSERT(iface_index == addr.sin6_scope_id);
-}
+ addr = uv_ip6_addr(scoped_addr, TEST_PORT);
+ LOGF("Got scope_id 0x%02x\n", addr.sin6_scope_id);
+ ASSERT(iface_index == addr.sin6_scope_id);
+ }
+ uv_free_interface_addresses(addresses, count);
-TEST_IMPL(ip6_addr_link_local) {
-#ifdef UV_PLATFORM_HAS_IP6_LINK_LOCAL_ADDRESS
- foreach_ip6_interface(&test_ip6_addr_scope);
+ MAKE_VALGRIND_HAPPY();
return 0;
#else
RETURN_SKIP("Qualified link-local addresses are not supported.");
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index d3371a809..feca46700 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -134,6 +134,7 @@ TEST_DECLARE (has_ref)
TEST_DECLARE (active)
TEST_DECLARE (embed)
TEST_DECLARE (async)
+TEST_DECLARE (async_null_cb)
TEST_DECLARE (get_currentexe)
TEST_DECLARE (process_title)
TEST_DECLARE (cwd_and_chdir)
@@ -396,6 +397,7 @@ TASK_LIST_START
TEST_ENTRY (embed)
TEST_ENTRY (async)
+ TEST_ENTRY (async_null_cb)
TEST_ENTRY (get_currentexe)
diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp
index 0e377d122..da254a1ab 100644
--- a/deps/uv/uv.gyp
+++ b/deps/uv/uv.gyp
@@ -302,6 +302,7 @@
'test/test-util.c',
'test/test-active.c',
'test/test-async.c',
+ 'test/test-async-null-cb.c',
'test/test-callback-stack.c',
'test/test-callback-order.c',
'test/test-connection-fail.c',