From a784abaff631449533d44846987c1537c080e03d Mon Sep 17 00:00:00 2001 From: Timothy J Fontaine Date: Wed, 21 Aug 2013 11:15:21 -0700 Subject: [PATCH] uv: Upgrade to v0.11.8 --- deps/uv/ChangeLog | 53 ++++++- deps/uv/Makefile.am | 3 +- deps/uv/autogen.sh | 31 ++++- deps/uv/configure.ac | 7 +- deps/uv/include/uv.h | 6 + deps/uv/src/queue.h | 4 +- deps/uv/src/unix/async.c | 7 +- deps/uv/src/unix/darwin-proctitle.c | 29 +++- deps/uv/src/unix/darwin.c | 139 +------------------ deps/uv/src/unix/fs.c | 4 + deps/uv/src/unix/fsevents.c | 267 +++++++++++++++++++++++++++++++----- deps/uv/src/unix/internal.h | 31 +++-- deps/uv/src/unix/kqueue.c | 1 + deps/uv/src/unix/process.c | 4 +- deps/uv/src/unix/proctitle.c | 3 +- deps/uv/src/unix/signal.c | 2 +- deps/uv/src/unix/stream.c | 2 + deps/uv/src/unix/threadpool.c | 5 +- deps/uv/src/uv-common.c | 10 +- deps/uv/src/uv-common.h | 10 -- deps/uv/src/version.c | 2 +- deps/uv/src/win/async.c | 6 +- deps/uv/src/win/internal.h | 5 + deps/uv/src/win/tcp.c | 2 +- deps/uv/test/test-async-null-cb.c | 55 ++++++++ deps/uv/test/test-ip6-addr.c | 90 ++++++------ deps/uv/test/test-list.h | 2 + deps/uv/uv.gyp | 1 + 28 files changed, 513 insertions(+), 268 deletions(-) create mode 100644 deps/uv/test/test-async-null-cb.c diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 8601b32..36b3283 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 8101110..e683f00 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 ed07953..751b4f5 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 f50e635..d9760a3 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 5c993b4..5821cce 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 2f5ab61..aa15837 100644 --- a/deps/uv/src/queue.h +++ b/deps/uv/src/queue.h @@ -16,8 +16,6 @@ #ifndef QUEUE_H_ #define QUEUE_H_ -#include - 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 f526ba3..5ced3cb 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 56c1417..90b2e41 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 +#include +#include + #include #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 81570f3..8a9b4ba 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -29,8 +29,6 @@ #include #include -#include - #include #include #include /* _NSGetExecutablePath */ @@ -38,154 +36,29 @@ #include #include /* 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 ecd2b23..6cabf51 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 ef9a352..79ad198 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 #include +#include + +#include #include 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 2c4e3e9..8559e33 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -39,7 +39,6 @@ #if defined(__sun) # include # include -# 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 f23391f..2c68bf3 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 c37bb3e..a9ecb45 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 8ffebb1..16b0523 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 5839098..53e524a 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 6d1144f..5f42c34 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 5a3a5f5..7923250 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 532f53f..95f5011 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 f3d7368..dc15091 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 e18cf15..e0a621f 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 edf6529..e192ead 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 7eaf410..98c96a7 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 8778714..5ed7976 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 0000000..d654884 --- /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 9cd9b97..91891bf 100644 --- a/deps/uv/test/test-ip6-addr.c +++ b/deps/uv/test/test-ip6-addr.c @@ -30,72 +30,68 @@ # include #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 d3371a8..feca467 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 0e377d1..da254a1 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', -- 2.7.4