From 97b85e8b75b8f3df774b6e008dbaa143daa412b7 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 7 Sep 2019 14:55:40 -0400 Subject: [PATCH] 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 Reviewed-By: Saúl Ibarra Corretgé diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index c04e7a48..ad09f403 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -454,10 +454,26 @@ int uv_fs_event_start(uv_fs_event_t* handle, const char* path, unsigned int flags) { int fd; +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + struct stat statbuf; +#endif if (uv__is_active(handle)) 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 /* Nullify field to perform checks later */ handle->cf_cb = NULL; @@ -465,14 +481,17 @@ int uv_fs_event_start(uv_fs_event_t* handle, handle->realpath_len = 0; 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) { 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->path = uv__strdup(path); - if (handle->path == NULL) - return UV_ENOMEM; - handle->cb = cb; r = uv__fsevents_init(handle); if (r == 0) { uv__handle_start(handle); @@ -482,20 +501,9 @@ int uv_fs_event_start(uv_fs_event_t* handle, } return r; } +fallback: #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__io_init(&handle->event_watcher, uv__fs_event, fd); 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); #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); #endif diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index ea34bd63..4b8bb1ef 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -656,6 +656,12 @@ TEST_IMPL(fs_event_watch_file_current_dir) { /* Setup */ remove("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); ASSERT(r == 0);