diff --git a/deps/uv/config-mingw.mk b/deps/uv/config-mingw.mk index 89bf2df391..9e49ec71b2 100644 --- a/deps/uv/config-mingw.mk +++ b/deps/uv/config-mingw.mk @@ -37,8 +37,8 @@ RUNNER_LINKFLAGS=$(LINKFLAGS) RUNNER_LIBS=-lws2_32 -lpsapi -liphlpapi RUNNER_SRC=test/runner-win.c -uv.a: $(WIN_OBJS) src/cares.o src/uv-common.o $(CARES_OBJS) - $(AR) rcs uv.a $(WIN_OBJS) src/cares.o src/uv-common.o $(CARES_OBJS) +uv.a: $(WIN_OBJS) src/cares.o src/fs-poll.o src/uv-common.o $(CARES_OBJS) + $(AR) rcs uv.a $^ src/%.o: src/%.c include/uv.h include/uv-private/uv-win.h $(CC) $(CFLAGS) -c $< -o $@ diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index c1ba2d0ad1..7220f108ad 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -129,8 +129,8 @@ endif RUNNER_LIBS= RUNNER_SRC=test/runner-unix.c -uv.a: $(OBJS) src/cares.o src/uv-common.o src/unix/ev/ev.o src/unix/uv-eio.o src/unix/eio/eio.o $(CARES_OBJS) - $(AR) rcs uv.a $(OBJS) src/cares.o src/uv-common.o src/unix/uv-eio.o src/unix/ev/ev.o src/unix/eio/eio.o $(CARES_OBJS) +uv.a: $(OBJS) src/cares.o src/fs-poll.o src/uv-common.o src/unix/ev/ev.o src/unix/uv-eio.o src/unix/eio/eio.o $(CARES_OBJS) + $(AR) rcs uv.a $^ src/%.o: src/%.c include/uv.h include/uv-private/uv-unix.h $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ diff --git a/deps/uv/include/uv-private/uv-unix.h b/deps/uv/include/uv-private/uv-unix.h index 62bb0aa45e..da185e29da 100644 --- a/deps/uv/include/uv-private/uv-unix.h +++ b/deps/uv/include/uv-private/uv-unix.h @@ -28,13 +28,17 @@ #include "eio.h" #include +#include +#include + #include #include #include #include #include -#include + #include +#include #include #include @@ -55,6 +59,8 @@ typedef int uv_file; typedef int uv_os_sock_t; +typedef struct stat uv_statbuf_t; + #define UV_ONCE_INIT PTHREAD_ONCE_INIT typedef pthread_once_t uv_once_t; diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h index 10a8ec0c78..43358da8ec 100644 --- a/deps/uv/include/uv-private/uv-win.h +++ b/deps/uv/include/uv-private/uv-win.h @@ -165,6 +165,8 @@ typedef struct uv_buf_t { typedef int uv_file; +typedef struct _stati64 uv_statbuf_t; + typedef SOCKET uv_os_sock_t; typedef HANDLE uv_thread_t; diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 8bd387accf..9b0e76b980 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -140,6 +140,7 @@ typedef enum { XX(ASYNC, async) \ XX(CHECK, check) \ XX(FS_EVENT, fs_event) \ + XX(FS_POLL, fs_poll) \ XX(IDLE, idle) \ XX(NAMED_PIPE, pipe) \ XX(POLL, poll) \ @@ -209,6 +210,7 @@ typedef struct uv_udp_send_s uv_udp_send_t; typedef struct uv_fs_s uv_fs_t; /* uv_fs_event_t is a subclass of uv_handle_t. */ typedef struct uv_fs_event_s uv_fs_event_t; +typedef struct uv_fs_poll_s uv_fs_poll_t; typedef struct uv_work_s uv_work_t; @@ -312,6 +314,11 @@ typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg); typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename, int events, int status); +typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle, + int status, + uv_statbuf_t* prev, + uv_statbuf_t* curr); + typedef enum { UV_LEAVE_GROUP = 0, UV_JOIN_GROUP @@ -1510,6 +1517,46 @@ struct uv_fs_event_s { }; +/* + * uv_fs_stat() based polling file watcher. + */ +struct uv_fs_poll_s { + UV_HANDLE_FIELDS + /* Private, don't touch. */ + int busy_polling; /* TODO(bnoordhuis) Fold into flags field. */ + unsigned int interval; + uint64_t start_time; + char* path; + uv_fs_poll_cb poll_cb; + uv_timer_t timer_handle; + uv_fs_t* fs_req; + uv_statbuf_t statbuf; +}; + +UV_EXTERN int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle); + +/* + * Check the file at `path` for changes every `interval` milliseconds. + * + * Your callback i invoked with `status == -1` if `path` does not exist + * or is inaccessible. The watcher is *not* stopped but your callback is + * not called again until something changes (e.g. when the file is created + * or the error reason changes). + * + * When `status == 0`, your callback receives pointers to the old and new + * `uv_statbuf_t` structs. They are valid for the duration of the callback + * only! + * + * For maximum portability, use multi-second intervals. Sub-second intervals + * will not detect all changes on many file systems. + */ +UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle, + uv_fs_poll_cb poll_cb, + const char* path, + unsigned int interval); + +UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle); + /* * Gets load avg * See: http://en.wikipedia.org/wiki/Load_(computing) @@ -1683,22 +1730,23 @@ union uv_any_req { struct uv_counters_s { + uint64_t async_init; + uint64_t check_init; uint64_t eio_init; - uint64_t req_init; + uint64_t fs_event_init; + uint64_t fs_poll_init; uint64_t handle_init; - uint64_t stream_init; - uint64_t tcp_init; - uint64_t udp_init; + uint64_t idle_init; uint64_t pipe_init; - uint64_t tty_init; uint64_t poll_init; uint64_t prepare_init; - uint64_t check_init; - uint64_t idle_init; - uint64_t async_init; - uint64_t timer_init; uint64_t process_init; - uint64_t fs_event_init; + uint64_t req_init; + uint64_t stream_init; + uint64_t tcp_init; + uint64_t timer_init; + uint64_t tty_init; + uint64_t udp_init; }; diff --git a/deps/uv/src/fs-poll.c b/deps/uv/src/fs-poll.c new file mode 100644 index 0000000000..61438f916f --- /dev/null +++ b/deps/uv/src/fs-poll.c @@ -0,0 +1,235 @@ +/* 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 "uv-common.h" + +#include +#include +#include + +static int statbuf_eq(const uv_statbuf_t* a, const uv_statbuf_t* b); +static void timer_cb(uv_timer_t* timer, int status); +static void poll_cb(uv_fs_t* req); + + +int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) { + /* TODO(bnoordhuis) Mark fs_req internal. */ + uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL); + loop->counters.fs_poll_init++; + + if (uv_timer_init(loop, &handle->timer_handle)) + return -1; + + handle->timer_handle.flags |= UV__HANDLE_INTERNAL; + uv__handle_unref(&handle->timer_handle); + + return 0; +} + + +int uv_fs_poll_start(uv_fs_poll_t* handle, + uv_fs_poll_cb cb, + const char* path, + unsigned int interval) { + uv_fs_t* req; + size_t len; + + if (uv__is_active(handle)) + return 0; + + len = strlen(path) + 1; + req = malloc(sizeof(*req) + len); + + if (req == NULL) + return uv__set_artificial_error(handle->loop, UV_ENOMEM); + + req->data = handle; + handle->path = memcpy(req + 1, path, len); + handle->fs_req = req; + handle->poll_cb = cb; + handle->interval = interval ? interval : 1; + handle->start_time = uv_now(handle->loop); + handle->busy_polling = 0; + memset(&handle->statbuf, 0, sizeof(handle->statbuf)); + + if (uv_fs_stat(handle->loop, handle->fs_req, handle->path, poll_cb)) + abort(); + + uv__handle_start(handle); + + return 0; +} + + +int uv_fs_poll_stop(uv_fs_poll_t* handle) { + if (!uv__is_active(handle)) + return 0; + + /* Don't free the fs req if it's active. Signal poll_cb that it needs to free + * the req by removing the handle backlink. + * + * TODO(bnoordhuis) Have uv-unix postpone the close callback until the req + * finishes so we don't need this pointer / lifecycle hackery. The callback + * always runs on the next tick now. + */ + if (handle->fs_req->data) + handle->fs_req->data = NULL; + else + free(handle->fs_req); + + handle->fs_req = NULL; + handle->path = NULL; + + uv_timer_stop(&handle->timer_handle); + uv__handle_stop(handle); + + return 0; +} + + +void uv__fs_poll_close(uv_fs_poll_t* handle) { + uv_fs_poll_stop(handle); + uv_close((uv_handle_t*)&handle->timer_handle, NULL); +} + + +static void timer_cb(uv_timer_t* timer, int status) { + uv_fs_poll_t* handle; + + handle = container_of(timer, uv_fs_poll_t, timer_handle); + handle->start_time = uv_now(handle->loop); + handle->fs_req->data = handle; + + if (uv_fs_stat(handle->loop, handle->fs_req, handle->path, poll_cb)) + abort(); + + assert(uv__is_active(handle)); +} + + +static void poll_cb(uv_fs_t* req) { + uv_statbuf_t* statbuf; + uv_fs_poll_t* handle; + uint64_t interval; + + handle = req->data; + + if (handle == NULL) /* Handle has been stopped or closed. */ + goto out; + + assert(req == handle->fs_req); + + if (req->result != 0) { + if (handle->busy_polling != -req->errorno) { + uv__set_artificial_error(handle->loop, req->errorno); + handle->poll_cb(handle, -1, NULL, NULL); + handle->busy_polling = -req->errorno; + } + goto out; + } + + statbuf = req->ptr; + + if (handle->busy_polling != 0) + if (handle->busy_polling < 0 || !statbuf_eq(&handle->statbuf, statbuf)) + handle->poll_cb(handle, 0, &handle->statbuf, statbuf); + + handle->statbuf = *statbuf; + handle->busy_polling = 1; + +out: + uv_fs_req_cleanup(req); + + if (req->data == NULL) { /* Handle has been stopped or closed. */ + free(req); + return; + } + + req->data = NULL; /* Tell uv_fs_poll_stop() it's safe to free the req. */ + + /* Reschedule timer, subtract the delay from doing the stat(). */ + interval = handle->interval; + interval -= (uv_now(handle->loop) - handle->start_time) % interval; + + if (uv_timer_start(&handle->timer_handle, timer_cb, interval, 0)) + abort(); +} + + +static int statbuf_eq(const uv_statbuf_t* a, const uv_statbuf_t* b) { +#ifdef _WIN32 + return a->st_mtime == b->st_mtime + && a->st_size == b->st_size + && a->st_mode == b->st_mode; +#else + + /* Jump through a few hoops to get sub-second granularity on Linux. */ +# if __linux__ +# if __USE_MISC /* _BSD_SOURCE || _SVID_SOURCE */ + if (a->st_ctim.tv_nsec != b->st_ctim.tv_nsec) return 0; + if (a->st_mtim.tv_nsec != b->st_mtim.tv_nsec) return 0; +# else + if (a->st_ctimensec != b->st_ctimensec) return 0; + if (a->st_mtimensec != b->st_mtimensec) return 0; +# endif +# endif + + /* Jump through different hoops on OS X. */ +# if __APPLE__ +# if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) + if (a->st_ctimespec.tv_nsec != b->st_ctimespec.tv_nsec) return 0; + if (a->st_mtimespec.tv_nsec != b->st_mtimespec.tv_nsec) return 0; +# else + if (a->st_ctimensec != b->st_ctimensec) return 0; + if (a->st_mtimensec != b->st_mtimensec) return 0; +# endif +# endif + + /* TODO(bnoordhuis) Other Unices have st_ctim and friends too, provided + * the stars and compiler flags are right... + */ + + return a->st_ctime == b->st_ctime + && a->st_mtime == b->st_mtime + && a->st_size == b->st_size + && a->st_mode == b->st_mode + && a->st_uid == b->st_uid + && a->st_gid == b->st_gid + && a->st_ino == b->st_ino + && a->st_dev == b->st_dev; +#endif +} + + +#ifdef _WIN32 + +#include "win/internal.h" +#include "win/handle-inl.h" + +void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) { + assert(handle->flags & UV_HANDLE_CLOSING); + assert(!(handle->flags & UV_HANDLE_CLOSED)); + uv__handle_stop(handle); + uv__handle_close(handle); +} + +#endif /* _WIN32 */ diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 524ffd0c61..318eb7184e 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -109,6 +109,10 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { uv__poll_close((uv_poll_t*)handle); break; + case UV_FS_POLL: + uv__fs_poll_close((uv_fs_poll_t*)handle); + break; + default: assert(0); } @@ -133,6 +137,9 @@ static void uv__finish_close(uv_handle_t* handle) { case UV_ASYNC: case UV_TIMER: case UV_PROCESS: + case UV_FS_EVENT: + case UV_FS_POLL: + case UV_POLL: break; case UV_NAMED_PIPE: @@ -148,12 +155,6 @@ static void uv__finish_close(uv_handle_t* handle) { uv__udp_finish_close((uv_udp_t*)handle); break; - case UV_FS_EVENT: - break; - - case UV_POLL: - break; - default: assert(0); break; diff --git a/deps/uv/src/unix/linux/syscalls.c b/deps/uv/src/unix/linux/syscalls.c index 4a1f8bc07f..5eb826b7c5 100644 --- a/deps/uv/src/unix/linux/syscalls.c +++ b/deps/uv/src/unix/linux/syscalls.c @@ -135,7 +135,7 @@ # elif __i386__ # define __NR_sendmmsg 345 # elif __arm__ -# define __NR_recvmmsg (UV_SYSCALL_BASE + 374) +# define __NR_sendmmsg (UV_SYSCALL_BASE + 374) # endif #endif /* __NR_sendmmsg */ diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index d5867acb6a..bfe02bb17a 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -213,6 +213,7 @@ void uv__fs_event_close(uv_fs_event_t* handle) { free(handle->filename); handle->filename = NULL; handle->fo.fo_name = NULL; + uv__handle_stop(handle); } #else /* !HAVE_PORTS_FS */ diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index 4c316ec11d..d159727d6c 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -86,6 +86,8 @@ int uv__tcp_connect6(uv_connect_t* req, struct sockaddr_in6 address, uv_connect_cb cb); +void uv__fs_poll_close(uv_fs_poll_t* handle); + UNUSED static int uv__has_active_reqs(const uv_loop_t* loop) { return !ngx_queue_empty(&loop->active_reqs); diff --git a/deps/uv/src/win/handle-inl.h b/deps/uv/src/win/handle-inl.h index ea2d9e0bc5..4064c24cf9 100644 --- a/deps/uv/src/win/handle-inl.h +++ b/deps/uv/src/win/handle-inl.h @@ -131,6 +131,10 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) { uv_fs_event_endgame(loop, (uv_fs_event_t*) handle); break; + case UV_FS_POLL: + uv__fs_poll_endgame(loop, (uv_fs_poll_t*) handle); + break; + default: assert(0); break; diff --git a/deps/uv/src/win/handle.c b/deps/uv/src/win/handle.c index 9343d256e1..d4b86de99e 100644 --- a/deps/uv/src/win/handle.c +++ b/deps/uv/src/win/handle.c @@ -132,6 +132,12 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) { uv_fs_event_close(loop, (uv_fs_event_t*) handle); return; + case UV_FS_POLL: + uv__fs_poll_close((uv_fs_poll_t*) handle); + uv__handle_start(handle); + uv_want_endgame(loop, handle); + return; + default: /* Not supported */ abort(); diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index 30d9e8c5b4..aaae66e7a3 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -268,6 +268,12 @@ void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle); void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle); +/* + * Stat poller. + */ +void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle); + + /* * Utilities. */ diff --git a/deps/uv/test/test-fs-poll.c b/deps/uv/test/test-fs-poll.c new file mode 100644 index 0000000000..d1c90e2ce2 --- /dev/null +++ b/deps/uv/test/test-fs-poll.c @@ -0,0 +1,147 @@ +/* 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" + +#include + +#define FIXTURE "testfile" + +static void timer_cb(uv_timer_t* handle, int status); +static void close_cb(uv_handle_t* handle); +static void poll_cb(uv_fs_poll_t* handle, + int status, + uv_statbuf_t* prev, + uv_statbuf_t* curr); + +static uv_fs_poll_t poll_handle; +static uv_timer_t timer_handle; +static uv_loop_t* loop; + +static int poll_cb_called; +static int timer_cb_called; +static int close_cb_called; + + +static void touch_file(const char* path) { + static int count; + FILE* fp; + int i; + + ASSERT((fp = fopen(FIXTURE, "w+"))); + + /* Need to change the file size because the poller may not pick up + * sub-second mtime changes. + */ + i = ++count; + + while (i--) + fputc('*', fp); + + fclose(fp); +} + + +static void close_cb(uv_handle_t* handle) { + close_cb_called++; +} + + +static void timer_cb(uv_timer_t* handle, int status) { + touch_file(FIXTURE); + timer_cb_called++; +} + + +static void poll_cb(uv_fs_poll_t* handle, + int status, + uv_statbuf_t* prev, + uv_statbuf_t* curr) { + ASSERT(handle == &poll_handle); + ASSERT(uv_is_active((uv_handle_t*)handle)); + + switch (poll_cb_called++) { + case 0: + ASSERT(status == -1); + ASSERT(prev == NULL); + ASSERT(curr == NULL); + ASSERT(uv_last_error(loop).code == UV_ENOENT); + touch_file(FIXTURE); + break; + + case 1: + ASSERT(status == 0); + ASSERT(prev != NULL); + ASSERT(curr != NULL); + { + uv_statbuf_t buf; + memset(&buf, 0, sizeof(buf)); + ASSERT(0 == memcmp(&buf, prev, sizeof(buf))); + } + ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 20, 0)); + break; + + case 2: + ASSERT(status == 0); + ASSERT(prev != NULL); + ASSERT(curr != NULL); + ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 200, 0)); + break; + + case 3: + ASSERT(status == 0); + ASSERT(prev != NULL); + ASSERT(curr != NULL); + remove(FIXTURE); + break; + + case 4: + ASSERT(status == -1); + ASSERT(prev == NULL); + ASSERT(curr == NULL); + ASSERT(uv_last_error(loop).code == UV_ENOENT); + uv_close((uv_handle_t*)handle, close_cb); + break; + + default: + ASSERT(0); + } +} + + +TEST_IMPL(fs_poll) { + loop = uv_default_loop(); + + remove(FIXTURE); + + ASSERT(0 == uv_timer_init(loop, &timer_handle)); + ASSERT(0 == uv_fs_poll_init(loop, &poll_handle)); + ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb, FIXTURE, 100)); + ASSERT(0 == uv_run(loop)); + + ASSERT(poll_cb_called == 5); + ASSERT(timer_cb_called == 2); + ASSERT(close_cb_called == 1); + uv_loop_delete(loop); + + return 0; +} diff --git a/deps/uv/test/test-hrtime.c b/deps/uv/test/test-hrtime.c index 91059f03af..2a9156ecf9 100644 --- a/deps/uv/test/test-hrtime.c +++ b/deps/uv/test/test-hrtime.c @@ -33,7 +33,7 @@ TEST_IMPL(hrtime) { uint64_t a, b, diff; - int i = 100; + int i = 75; while (i > 0) { a = uv_hrtime(); uv_sleep(45); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 9af246dd7b..cf9a02edb1 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -97,6 +97,7 @@ TEST_DECLARE (unref_in_prepare_cb) TEST_DECLARE (timer_ref) TEST_DECLARE (timer_ref2) TEST_DECLARE (fs_event_ref) +TEST_DECLARE (fs_poll_ref) TEST_DECLARE (tcp_ref) TEST_DECLARE (tcp_ref2) TEST_DECLARE (tcp_ref3) @@ -134,6 +135,7 @@ TEST_DECLARE (spawn_and_ping) TEST_DECLARE (spawn_setuid_fails) TEST_DECLARE (spawn_setgid_fails) TEST_DECLARE (spawn_stdout_to_file) +TEST_DECLARE (fs_poll) TEST_DECLARE (kill) TEST_DECLARE (fs_file_noent) TEST_DECLARE (fs_file_nametoolong) @@ -293,6 +295,7 @@ TASK_LIST_START TEST_ENTRY (ref) TEST_ENTRY (idle_ref) + TEST_ENTRY (fs_poll_ref) TEST_ENTRY (async_ref) TEST_ENTRY (prepare_ref) TEST_ENTRY (check_ref) @@ -360,6 +363,7 @@ TASK_LIST_START TEST_ENTRY (spawn_setuid_fails) TEST_ENTRY (spawn_setgid_fails) TEST_ENTRY (spawn_stdout_to_file) + TEST_ENTRY (fs_poll) TEST_ENTRY (kill) #ifdef _WIN32 TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows) diff --git a/deps/uv/test/test-ref.c b/deps/uv/test/test-ref.c index cc59aa7b6c..e0c38858ec 100644 --- a/deps/uv/test/test-ref.c +++ b/deps/uv/test/test-ref.c @@ -168,6 +168,16 @@ TEST_IMPL(fs_event_ref) { } +TEST_IMPL(fs_poll_ref) { + uv_fs_poll_t h; + uv_fs_poll_init(uv_default_loop(), &h); + uv_fs_poll_start(&h, NULL, ".", 999); + uv_unref((uv_handle_t*)&h); + uv_run(uv_default_loop()); + return 0; +} + + TEST_IMPL(tcp_ref) { uv_tcp_t h; uv_tcp_init(uv_default_loop(), &h); diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 0a519b7949..63f3ec0e5a 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -50,6 +50,7 @@ 'include/uv-private/ngx-queue.h', 'include/uv-private/tree.h', 'src/cares.c', + 'src/fs-poll.c', 'src/uv-common.c', 'src/uv-common.h', 'src/ares/ares_cancel.c', @@ -339,6 +340,7 @@ 'test/test-shutdown-close.c', 'test/test-shutdown-eof.c', 'test/test-spawn.c', + 'test/test-fs-poll.c', 'test/test-stdio-over-pipes.c', 'test/test-tcp-bind-error.c', 'test/test-tcp-bind6-error.c',