diff options
31 files changed, 566 insertions, 323 deletions
diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 560a650018..5dc4075e39 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -2,6 +2,7 @@ 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> diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 32793e193e..1562f4a680 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -84,3 +84,4 @@ Ben Kelly <ben@wanderview.com> Kristian Evensen <kristian.evensen@gmail.com> Nils Maier <maierman@web.de> Nicholas Vavilov <vvnicholas@gmail.com> +Miroslav Bajtoš <miro.bajtos@gmail.com> diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 99798d767e..c96f8086ef 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,4 +1,73 @@ -2013.04.11, Version 0.11.1 (Unstable) +2013.05.11, Version 0.11.2 (Unstable) + +Changes since version 0.11.1: + +* darwin: look up file path with F_GETPATH (Ben Noordhuis) + +* unix, windows: add uv_has_ref() function (Saúl Ibarra Corretgé) + +* build: avoid double / in paths for dtrace (Timothy J. Fontaine) + +* unix: remove src/unix/cygwin.c (Ben Noordhuis) + +* windows: deal with the fact that GetTickCount might lag (Bert Belder) + +* unix: silence STATIC_ASSERT compiler warnings (Ben Noordhuis) + +* linux: don't use fopen() in uv_resident_set_memory() (Ben Noordhuis) + + +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.04.11, Version 0.11.1 (Unstable), 5c10e82ae0bc99eff86d4b9baff1f1aa0bf84c0a This is the first versioned release from the current unstable libuv branch. @@ -36,7 +105,7 @@ Changes since Node.js v0.11.0: * build: add support for Visual Studio 2012 (Nicholas Vavilov) -2013.02.04, Version 0.10.3 (Stable) +2013.03.28, Version 0.10.3 (Stable), 31ebe23973dd98fd8a24c042b606f37a794e99d0 Changes since version 0.10.2: @@ -53,7 +122,7 @@ Changes since version 0.10.2: * unix: don't clear flags after closing UDP handle (Saúl Ibarra Corretgé) -2013.03.25, Version 0.10.2 (Stable) +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. diff --git a/deps/uv/build.mk b/deps/uv/build.mk index 00c71a5378..d3a9046b9a 100644 --- a/deps/uv/build.mk +++ b/deps/uv/build.mk @@ -88,6 +88,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 \ diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index e126a30d75..3cecb57bde 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -18,8 +18,6 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -OBJC ?= $(CC) - E= CSTDFLAG=--std=c89 -pedantic -Wall -Wextra -Wno-unused-parameter CFLAGS += -g @@ -80,8 +78,12 @@ endif ifeq (darwin,$(PLATFORM)) HAVE_DTRACE=1 -# dtrace(1) probes contain dollar signs. +# 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 \ @@ -130,13 +132,6 @@ OBJS += src/unix/openbsd.o OBJS += src/unix/kqueue.o endif -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,$(PLATFORM)) RUNNER_LDFLAGS += -pthreads else @@ -181,9 +176,6 @@ test/%.o: test/%.c include/uv.h test/.buildstamp clean-platform: $(RM) test/run-{tests,benchmarks}.dSYM $(OBJS) $(OBJS:%.o=%.pic.o) src/unix/uv-dtrace.h -%.pic.o %.o: %.m - $(OBJC) $(CPPFLAGS) $(CFLAGS) -c $^ -o $@ - src/unix/uv-dtrace.h: src/unix/uv-dtrace.d dtrace -h -xnolibs -s $< -o $@ diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h index 4f0b7b1aa2..0ca4bc28b6 100644 --- a/deps/uv/include/uv-private/uv-win.h +++ b/deps/uv/include/uv-private/uv-win.h @@ -275,6 +275,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); HANDLE iocp; \ /* The current time according to the event loop. in msecs. */ \ uint64_t time; \ + /* GetTickCount() result when the event loop time was last updated. */ \ + DWORD last_tick_count; \ /* Tail of a single-linked circular queue of pending reqs. If the queue */ \ /* is empty, tail_ is NULL. If there is only one item, */ \ /* tail_->next_req == tail_ */ \ diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 3b61e28f60..a3ebaa40b5 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -281,6 +281,7 @@ UV_EXTERN void uv_stop(uv_loop_t*); */ UV_EXTERN void uv_ref(uv_handle_t*); UV_EXTERN void uv_unref(uv_handle_t*); +UV_EXTERN int uv_has_ref(const uv_handle_t*); UV_EXTERN void uv_update_time(uv_loop_t*); UV_EXTERN uint64_t uv_now(uv_loop_t*); @@ -579,9 +580,9 @@ UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client); /* * Read data from an incoming stream. The callback will be made several - * several times until there is no more data to read or uv_read_stop is - * called. When we've reached EOF nread will be set to -1 and the error is - * set to UV_EOF. When nread == -1 the buf parameter might not point to a + * times until there is no more data to read or uv_read_stop is called. + * When we've reached EOF nread will be set to -1 and the error is set + * to UV_EOF. When nread == -1 the buf parameter might not point to a * valid buffer; in that case buf.len and buf.base are both set to 0. * Note that nread might also be 0, which does *not* indicate an error or * eof; it happens when libuv requested a buffer through the alloc callback @@ -1754,9 +1755,9 @@ UV_EXTERN int uv_signal_stop(uv_signal_t* handle); /* - * Gets load avg + * Gets load average. * See: http://en.wikipedia.org/wiki/Load_(computing) - * (Returns [0,0,0] for windows and cygwin) + * Returns [0,0,0] on Windows. */ UV_EXTERN void uv_loadavg(double avg[3]); diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 9268f40c37..98b48989a7 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/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) { diff --git a/deps/uv/src/unix/cygwin.c b/deps/uv/src/unix/cygwin.c deleted file mode 100644 index 9ee520d7ec..0000000000 --- a/deps/uv/src/unix/cygwin.c +++ /dev/null @@ -1,90 +0,0 @@ -/* 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 "internal.h" - -#include <assert.h> -#include <stdint.h> -#include <stddef.h> -#include <errno.h> -#include <unistd.h> -#include <time.h> - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - - -int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { -} - - -uint64_t uv__hrtime(void) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -} - - -void uv_loadavg(double avg[3]) { - /* Unsupported as of cygwin 1.7.7 */ - avg[0] = avg[1] = avg[2] = 0; -} - - -int uv_exepath(char* buffer, size_t* size) { - uint32_t usize; - - if (!buffer || !size) { - return -1; - } - - *size = readlink("/proc/self/exe", buffer, *size - 1); - if (*size <= 0) return -1; - buffer[*size] = '\0'; - return 0; -} - -uint64_t uv_get_free_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); -} - -uint64_t uv_get_total_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); -} - -int uv_fs_event_init(uv_loop_t* loop, - uv_fs_event_t* handle, - const char* filename, - uv_fs_event_cb cb, - int flags) { - uv__set_sys_error(loop, ENOSYS); - return -1; -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { - assert(0 && "implement me"); -} diff --git a/deps/uv/src/unix/darwin-proctitle.m b/deps/uv/src/unix/darwin-proctitle.c index d0ee95b498..e6c85905c0 100644 --- a/deps/uv/src/unix/darwin-proctitle.m +++ b/deps/uv/src/unix/darwin-proctitle.c @@ -18,7 +18,8 @@ * IN THE SOFTWARE. */ -#include <Cocoa/Cocoa.h> +#include <CoreFoundation/CoreFoundation.h> +#include <ApplicationServices/ApplicationServices.h> int uv__set_process_title(const char* title) { @@ -43,14 +44,14 @@ int uv__set_process_title(const char* title) { 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")); diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 899c972b08..2f4d526a61 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -26,6 +26,7 @@ #include <assert.h> #include <stdlib.h> /* abort */ +#include <string.h> /* strrchr */ #if defined(__STRICT_ANSI__) # define inline __inline @@ -46,7 +47,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)) @@ -256,6 +257,18 @@ static void uv__update_time(uv_loop_t* loop) { loop->time = uv__hrtime() / 1000000; } +__attribute__((unused)) +static char* uv__basename_r(const char* path) { + char* s; + + s = strrchr(path, '/'); + if (s == NULL) + return (char*) path; + + return s + 1; +} + + #ifdef HAVE_DTRACE #include "uv-dtrace.h" #else diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index 9ad06da4c0..fa40f6147e 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -259,6 +259,11 @@ static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) { uv_fs_event_t* handle; struct kevent ev; int events; + const char* path; +#if defined(F_GETPATH) + /* MAXPATHLEN == PATH_MAX but the former is what XNU calls it internally. */ + char pathbuf[MAXPATHLEN]; +#endif handle = container_of(w, uv_fs_event_t, event_watcher); @@ -267,7 +272,16 @@ static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) { else events = UV_RENAME; - handle->cb(handle, NULL, events, 0); + path = NULL; +#if defined(F_GETPATH) + /* Also works when the file has been unlinked from the file system. Passing + * in the path when the file has been deleted is arguably a little strange + * but it's consistent with what the inotify backend does. + */ + if (fcntl(handle->event_watcher.fd, F_GETPATH, pathbuf) == 0) + path = uv__basename_r(pathbuf); +#endif + handle->cb(handle, path, events, 0); if (handle->event_watcher.fd == -1) return; diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index 630f5a1ccc..7bb05b5d32 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/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; + + 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; - cbuf++; + 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); } diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c index 76b9dfa450..af0242477e 100644 --- a/deps/uv/src/unix/linux-inotify.c +++ b/deps/uv/src/unix/linux-inotify.c @@ -45,13 +45,6 @@ struct watcher_root { #define CAST(p) ((struct watcher_root*)(p)) -/* Don't look aghast, this is exactly how glibc's basename() works. */ -static char* basename_r(const char* path) { - char* s = strrchr(path, '/'); - return s ? (s + 1) : (char*)path; -} - - static int compare_watchers(const struct watcher_list* a, const struct watcher_list* b) { if (a->wd < b->wd) return -1; @@ -156,7 +149,7 @@ static void uv__inotify_read(uv_loop_t* loop, * for modifications. Repurpose the filename for API compatibility. * I'm not convinced this is a good thing, maybe it should go. */ - path = e->len ? (const char*) (e + 1) : basename_r(w->path); + path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); QUEUE_FOREACH(q, &w->watchers) { h = QUEUE_DATA(q, uv_fs_event_t, watchers); diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 7a185ab621..0c38231d68 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -46,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; @@ -139,7 +139,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,7 +148,7 @@ 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) */ @@ -202,12 +202,16 @@ static void uv__stream_osx_select(void* arg) { if (FD_ISSET(fd, &swrite)) events |= UV__POLLOUT; - 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)); + } } } @@ -240,10 +244,9 @@ 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(events != 0); assert(events == (events & (UV__POLLIN | UV__POLLOUT))); @@ -305,6 +308,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { if (s == NULL) return uv__set_artificial_error(stream->loop, UV_ENOMEM); + s->events = 0; s->fd = *fd; if (uv_async_init(stream->loop, &s->async, uv__stream_osx_select_cb)) { @@ -315,10 +319,10 @@ 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. */ @@ -343,9 +347,9 @@ fatal4: 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); @@ -437,7 +441,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; @@ -455,14 +458,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; } } @@ -475,10 +472,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); @@ -492,50 +488,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 (use_emfile_trick) { - SAVE_ERRNO(r = uv__emfile_trick(loop, uv__stream_fd(stream))); - if (r == 0) { - UV_DEC_BACKLOG(w) - continue; - } - } + if (errno == EAGAIN || errno == EWOULDBLOCK) + return; /* Not an error. */ - /* 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); @@ -1356,11 +1334,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); diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index e134b0a181..2413105c0f 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -189,6 +189,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w->cb(loop, w, pe->portev_events); nevents++; + if (w != loop->watchers[fd]) + continue; /* Disabled by callback. */ + /* Events Ports operates in oneshot mode, rearm timer on next run. */ if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index c95dfdd3e3..fc8831fd97 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -426,6 +426,11 @@ void uv_unref(uv_handle_t* handle) { } +int uv_has_ref(const uv_handle_t* handle) { + return uv__has_ref(handle); +} + + void uv_stop(uv_loop_t* loop) { loop->stop_flag = 1; } diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index e2d2f4bc12..6a47513be3 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -186,6 +186,9 @@ void uv__fs_poll_close(uv_fs_poll_t* handle); } \ while (0) +#define uv__has_ref(h) \ + (((h)->flags & UV__HANDLE_REF) != 0) + #if defined(_WIN32) # define uv__handle_platform_init(h) #else diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c index b413332499..0d502d01b7 100644 --- a/deps/uv/src/version.c +++ b/deps/uv/src/version.c @@ -29,7 +29,7 @@ #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 11 -#define UV_VERSION_PATCH 1 +#define UV_VERSION_PATCH 2 #define UV_VERSION_IS_RELEASE 1 diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index a8699e1985..3ba3203803 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -90,6 +90,7 @@ static void uv_loop_init(uv_loop_t* loop) { /* To prevent uninitialized memory access, loop->time must be intialized */ /* to zero before calling uv_update_time for the first time. */ loop->time = 0; + loop->last_tick_count = 0; uv_update_time(loop); QUEUE_INIT(&loop->handle_queue); @@ -205,12 +206,15 @@ static void uv_poll(uv_loop_t* loop, int block) { 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"); + } else { + /* We're sure that at least `timeout` milliseconds have expired, but */ + /* this may not be reflected yet in the GetTickCount() return value. */ + /* Therefore we ensure it's taken into account here. */ + uv__time_forward(loop, timeout); } } @@ -229,14 +233,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 */ @@ -246,6 +249,11 @@ static void uv_poll_ex(uv_loop_t* loop, int block) { } else if (GetLastError() != WAIT_TIMEOUT) { /* Serious error */ uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx"); + } else if (timeout > 0) { + /* We're sure that at least `timeout` milliseconds have expired, but */ + /* this may not be reflected yet in the GetTickCount() return value. */ + /* Therefore we ensure it's taken into account here. */ + uv__time_forward(loop, timeout); } } diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index 9920f704ab..f0909cdf0e 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -206,6 +206,7 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle); void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle); DWORD uv_get_poll_timeout(uv_loop_t* loop); +void uv__time_forward(uv_loop_t* loop, uint64_t msecs); void uv_process_timers(uv_loop_t* loop); diff --git a/deps/uv/src/win/timer.c b/deps/uv/src/win/timer.c index 0c055da941..52c124e892 100644 --- a/deps/uv/src/win/timer.c +++ b/deps/uv/src/win/timer.c @@ -29,19 +29,38 @@ void uv_update_time(uv_loop_t* loop) { - DWORD ticks = GetTickCount(); + DWORD ticks; + ULARGE_INTEGER time; - /* The assumption is made that LARGE_INTEGER.QuadPart has the same type */ - /* loop->time, which happens to be. Is there any way to assert this? */ - LARGE_INTEGER* time = (LARGE_INTEGER*) &loop->time; + ticks = GetTickCount(); - /* If the timer has wrapped, add 1 to it's high-order dword. */ + time.QuadPart = loop->time; + + /* GetTickCount() can conceivably wrap around, so when the current tick */ + /* count is lower than the last tick count, we'll assume it has wrapped. */ /* uv_poll must make sure that the timer can never overflow more than */ /* once between two subsequent uv_update_time calls. */ - if (ticks < time->LowPart) { - time->HighPart += 1; - } - time->LowPart = ticks; + time.LowPart = ticks; + if (ticks < loop->last_tick_count) + time.HighPart++; + + /* Remember the last tick count. */ + loop->last_tick_count = ticks; + + /* The GetTickCount() resolution isn't too good. Sometimes it'll happen */ + /* that GetQueuedCompletionStatus() or GetQueuedCompletionStatusEx() has */ + /* waited for a couple of ms but this is not reflected in the GetTickCount */ + /* result yet. Therefore whenever GetQueuedCompletionStatus times out */ + /* we'll add the number of ms that it has waited to the current loop time. */ + /* When that happened the loop time might be a little ms farther than what */ + /* we've just computed, and we shouldn't update the loop time. */ + if (loop->time < time.QuadPart) + loop->time = time.QuadPart; +} + + +void uv__time_forward(uv_loop_t* loop, uint64_t msecs) { + loop->time += msecs; } @@ -87,6 +106,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 +127,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 +173,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 +242,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/deps/uv/test/runner-unix.c b/deps/uv/test/runner-unix.c index eefb700835..b66df51b98 100644 --- a/deps/uv/test/runner-unix.c +++ b/deps/uv/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/deps/uv/test/runner-win.c b/deps/uv/test/runner-win.c index 3aae1c3e9c..5d23259437 100644 --- a/deps/uv/test/runner-win.c +++ b/deps/uv/test/runner-win.c @@ -248,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/deps/uv/test/runner.c b/deps/uv/test/runner.c index bda1080a18..d8e9ddeb01 100644 --- a/deps/uv/test/runner.c +++ b/deps/uv/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 @@ out: 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/deps/uv/test/runner.h b/deps/uv/test/runner.h index 8be9e39fcc..aa7f205407 100644 --- a/deps/uv/test/runner.h +++ b/deps/uv/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/deps/uv/test/task.h b/deps/uv/test/task.h index de7c80ec3a..308201e579 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/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/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 30a2a0a28f..0822d7f151 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -128,6 +128,7 @@ TEST_DECLARE (pipe_ref2) TEST_DECLARE (pipe_ref3) TEST_DECLARE (pipe_ref4) TEST_DECLARE (process_ref) +TEST_DECLARE (has_ref) TEST_DECLARE (active) TEST_DECLARE (embed) TEST_DECLARE (async) @@ -221,6 +222,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) @@ -377,6 +381,7 @@ TASK_LIST_START TEST_ENTRY (pipe_ref4) TEST_HELPER (pipe_ref4, pipe_echo_server) TEST_ENTRY (process_ref) + TEST_ENTRY (has_ref) TEST_ENTRY (loop_handles) TEST_ENTRY (walk_handles) @@ -442,6 +447,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/deps/uv/test/test-osx-select.c b/deps/uv/test/test-osx-select.c new file mode 100644 index 0000000000..5c2cbd4d93 --- /dev/null +++ b/deps/uv/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/deps/uv/test/test-ref.c b/deps/uv/test/test-ref.c index 9fc214ab60..37279ac89a 100644 --- a/deps/uv/test/test-ref.c +++ b/deps/uv/test/test-ref.c @@ -413,3 +413,15 @@ TEST_IMPL(process_ref) { MAKE_VALGRIND_HAPPY(); return 0; } + + +TEST_IMPL(has_ref) { + uv_idle_t h; + uv_idle_init(uv_default_loop(), &h); + uv_ref((uv_handle_t*)&h); + ASSERT(uv_has_ref((uv_handle_t*)&h) == 1); + uv_unref((uv_handle_t*)&h); + ASSERT(uv_has_ref((uv_handle_t*)&h) == 0); + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 6f1de77b0f..f2cdd538d3 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -5,7 +5,8 @@ # 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': '', + # XXX gyp is quite sensitive about paths with double / they don't normalize + 'uv_parent_path': '/', }, 'target_defaults': { @@ -176,7 +177,7 @@ 'sources': [ 'src/unix/darwin.c', 'src/unix/fsevents.c', - 'src/unix/darwin-proctitle.m', + 'src/unix/darwin-proctitle.c', ], 'link_settings': { 'libraries': [ @@ -235,21 +236,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()', { @@ -309,6 +305,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', @@ -475,10 +472,10 @@ 'action_name': 'uv_dtrace_o', 'inputs': [ 'src/unix/uv-dtrace.d', - '<(PRODUCT_DIR)/obj.target/libuv/<(uv_parent_path)/src/unix/core.o', + '<(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', + '<(PRODUCT_DIR)/obj.target/libuv<(uv_parent_path)src/unix/dtrace.o', ], 'action': [ 'dtrace', '-G', '-xnolibs', '-s', '<@(_inputs)', '-o', '<@(_outputs)' ] |