unix, windows: add stat() based file watcher
Monitors a file path for changes. Supersedes ev_stat.
This commit is contained in:
parent
9a3dff35c0
commit
cc7c8542a5
@ -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 $@
|
||||
|
||||
@ -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 $@
|
||||
|
||||
@ -249,6 +249,9 @@ struct uv__io_s {
|
||||
struct stat statbuf; \
|
||||
eio_req* eio;
|
||||
|
||||
#define UV_FS_POLL_PRIVATE_FIELDS \
|
||||
struct stat statbuf;
|
||||
|
||||
#define UV_WORK_PRIVATE_FIELDS \
|
||||
eio_req* eio;
|
||||
|
||||
|
||||
@ -487,6 +487,9 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
||||
}; \
|
||||
};
|
||||
|
||||
#define UV_FS_POLL_PRIVATE_FIELDS \
|
||||
struct _stati64 statbuf;
|
||||
|
||||
#define UV_WORK_PRIVATE_FIELDS \
|
||||
|
||||
#define UV_FS_EVENT_PRIVATE_FIELDS \
|
||||
|
||||
59
include/uv.h
59
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;
|
||||
|
||||
|
||||
@ -295,6 +297,7 @@ typedef void (*uv_async_cb)(uv_async_t* handle, int status);
|
||||
typedef void (*uv_prepare_cb)(uv_prepare_t* handle, int status);
|
||||
typedef void (*uv_check_cb)(uv_check_t* handle, int status);
|
||||
typedef void (*uv_idle_cb)(uv_idle_t* handle, int status);
|
||||
typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle, int status);
|
||||
typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* handle, int status,
|
||||
struct addrinfo* res);
|
||||
typedef void (*uv_exit_cb)(uv_process_t*, int exit_status, int term_signal);
|
||||
@ -1510,6 +1513,41 @@ 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_FS_POLL_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
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 gets invoked repeatedly with `status == -1` if `path`
|
||||
* does not exist or is inaccessible. The watcher is *not* stopped. This
|
||||
* lets you monitor a path until the resource becomes available (again).
|
||||
*
|
||||
* 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 +1721,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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
221
src/fs-poll.c
Normal file
221
src/fs-poll.c
Normal file
@ -0,0 +1,221 @@
|
||||
/* 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 <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef struct _stati64 uv__statbuf_t;
|
||||
#else
|
||||
typedef struct stat uv__statbuf_t;
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
/* TODO(bnoordhuis) Only signal the error the first time? What if the
|
||||
* error reason changes?
|
||||
*/
|
||||
uv__set_artificial_error(handle->loop, req->errorno);
|
||||
handle->poll_cb(handle, -1);
|
||||
handle->busy_polling = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
statbuf = req->ptr;
|
||||
|
||||
if (handle->busy_polling == 0) {
|
||||
handle->statbuf = *statbuf;
|
||||
handle->busy_polling = 1;
|
||||
}
|
||||
else if (handle->busy_polling == -1) {
|
||||
handle->statbuf = *statbuf;
|
||||
handle->busy_polling = 1;
|
||||
handle->poll_cb(handle, 0); /* Error went away. */
|
||||
}
|
||||
else if (!statbuf_eq(statbuf, &handle->statbuf)) {
|
||||
handle->statbuf = *statbuf;
|
||||
handle->poll_cb(handle, 0);
|
||||
}
|
||||
|
||||
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
|
||||
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 */
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
127
test/test-fs-poll.c
Normal file
127
test/test-fs-poll.c
Normal file
@ -0,0 +1,127 @@
|
||||
/* 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 <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define FIXTURE "testfile"
|
||||
|
||||
static void poll_cb(uv_fs_poll_t* handle, int status);
|
||||
static void timer_cb(uv_timer_t* handle, int status);
|
||||
static void close_cb(uv_handle_t* handle);
|
||||
|
||||
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) {
|
||||
ASSERT(handle == &poll_handle);
|
||||
ASSERT(uv_is_active((uv_handle_t*)handle));
|
||||
|
||||
switch (poll_cb_called++) {
|
||||
case 0:
|
||||
ASSERT(status == -1);
|
||||
ASSERT(uv_last_error(loop).code == UV_ENOENT);
|
||||
touch_file(FIXTURE);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ASSERT(status == 0);
|
||||
ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 20, 0));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ASSERT(status == 0);
|
||||
ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 200, 0));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ASSERT(status == 0);
|
||||
remove(FIXTURE);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ASSERT(status == -1);
|
||||
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;
|
||||
}
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
2
uv.gyp
2
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',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user