fsevents: stop using fsevents to watch files

Goes back to just using it to watch folders,
but keeps the other logic changes around.

Refs: https://github.com/libuv/libuv/pull/387
Refs: https://github.com/libuv/libuv/pull/2082
Refs: https://github.com/libuv/libuv/pull/1572
Refs: https://github.com/nodejs/node/issues/29460
Fixes: https://github.com/libuv/libuv/issues/2488
Closes: https://github.com/libuv/libuv/pull/2452
PR-URL: https://github.com/libuv/libuv/pull/2459
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Saúl Ibarra Corretgé <s@saghul.net>
This commit is contained in:
Jameson Nash 2019-09-07 14:55:40 -04:00 committed by Saúl Ibarra Corretgé
parent 501b5cc53e
commit 97b85e8b75
2 changed files with 32 additions and 18 deletions

View File

@ -454,10 +454,26 @@ int uv_fs_event_start(uv_fs_event_t* handle,
const char* path, const char* path,
unsigned int flags) { unsigned int flags) {
int fd; int fd;
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
struct stat statbuf;
#endif
if (uv__is_active(handle)) if (uv__is_active(handle))
return UV_EINVAL; return UV_EINVAL;
handle->cb = cb;
handle->path = uv__strdup(path);
if (handle->path == NULL)
return UV_ENOMEM;
/* TODO open asynchronously - but how do we report back errors? */
fd = open(handle->path, O_RDONLY);
if (fd == -1) {
uv__free(handle->path);
handle->path = NULL;
return UV__ERR(errno);
}
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
/* Nullify field to perform checks later */ /* Nullify field to perform checks later */
handle->cf_cb = NULL; handle->cf_cb = NULL;
@ -465,14 +481,17 @@ int uv_fs_event_start(uv_fs_event_t* handle,
handle->realpath_len = 0; handle->realpath_len = 0;
handle->cf_flags = flags; handle->cf_flags = flags;
if (fstat(fd, &statbuf))
goto fallback;
/* FSEvents works only with directories */
if (!(statbuf.st_mode & S_IFDIR))
goto fallback;
if (!uv__has_forked_with_cfrunloop) { if (!uv__has_forked_with_cfrunloop) {
int r; int r;
/* The fallback fd is not used */ /* The fallback fd is no longer needed */
uv__close_nocheckstdio(fd);
handle->event_watcher.fd = -1; handle->event_watcher.fd = -1;
handle->path = uv__strdup(path);
if (handle->path == NULL)
return UV_ENOMEM;
handle->cb = cb;
r = uv__fsevents_init(handle); r = uv__fsevents_init(handle);
if (r == 0) { if (r == 0) {
uv__handle_start(handle); uv__handle_start(handle);
@ -482,20 +501,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
} }
return r; return r;
} }
fallback:
#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ #endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
/* TODO open asynchronously - but how do we report back errors? */
fd = open(path, O_RDONLY);
if (fd == -1)
return UV__ERR(errno);
handle->path = uv__strdup(path);
if (handle->path == NULL) {
uv__close_nocheckstdio(fd);
return UV_ENOMEM;
}
handle->cb = cb;
uv__handle_start(handle); uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd); uv__io_init(&handle->event_watcher, uv__fs_event, fd);
uv__io_start(handle->loop, &handle->event_watcher, POLLIN); uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
@ -514,7 +522,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
uv__handle_stop(handle); uv__handle_stop(handle);
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
if (!uv__has_forked_with_cfrunloop) if (!uv__has_forked_with_cfrunloop && handle->cf_cb != NULL)
r = uv__fsevents_close(handle); r = uv__fsevents_close(handle);
#endif #endif

View File

@ -656,6 +656,12 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
/* Setup */ /* Setup */
remove("watch_file"); remove("watch_file");
create_file("watch_file"); create_file("watch_file");
#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_12)
/* Empirically, kevent seems to (sometimes) report the preceeding
* create_file events prior to macOS 10.11.6 in the subsequent fs_event_start
* So let the system settle before running the test. */
uv_sleep(1100);
#endif
r = uv_fs_event_init(loop, &fs_event); r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0); ASSERT(r == 0);