diff --git a/src/unix/fsevents.c b/src/unix/fsevents.c index e7a493ef..0818ba3d 100644 --- a/src/unix/fsevents.c +++ b/src/unix/fsevents.c @@ -76,7 +76,7 @@ typedef struct uv__cf_loop_state_s uv__cf_loop_state_t; struct uv__cf_loop_state_s { CFRunLoopRef loop; CFRunLoopSourceRef signal_source; - volatile int fsevent_need_reschedule; + int fsevent_need_reschedule; FSEventStreamRef fsevent_stream; uv_sem_t fsevent_sem; uv_mutex_t fsevent_mutex; @@ -360,9 +360,13 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle) { /* Optimization to prevent O(n^2) time spent when starting to watch * many files simultaneously */ - if (!state->fsevent_need_reschedule) - return; + uv_mutex_lock(&state->fsevent_mutex); + if (state->fsevent_need_reschedule == 0) { + uv_mutex_unlock(&state->fsevent_mutex); + goto final; + } state->fsevent_need_reschedule = 0; + uv_mutex_unlock(&state->fsevent_mutex); /* Destroy previous FSEventStream */ uv__fsevents_destroy_stream(handle->loop); @@ -399,6 +403,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle) { uv__fsevents_create_stream(handle->loop, cf_paths); } +final: /* * Main thread will block until the removal of handle from the list, * we must tell it when we're ready. diff --git a/test/test-fs-event.c b/test/test-fs-event.c index 1df2569d..a6f2d904 100644 --- a/test/test-fs-event.c +++ b/test/test-fs-event.c @@ -502,3 +502,31 @@ TEST_IMPL(fs_event_close_in_callback) { } #endif /* HAVE_KQUEUE */ + +TEST_IMPL(fs_event_start_and_close) { + uv_loop_t* loop; + uv_fs_event_t fs_event1; + uv_fs_event_t fs_event2; + int r; + + loop = uv_default_loop(); + + create_dir(loop, "watch_dir"); + + r = uv_fs_event_init(loop, &fs_event1, "watch_dir", fs_event_cb_dir, 0); + ASSERT(r == 0); + + r = uv_fs_event_init(loop, &fs_event2, "watch_dir", fs_event_cb_dir, 0); + ASSERT(r == 0); + + uv_close((uv_handle_t*) &fs_event2, close_cb); + uv_close((uv_handle_t*) &fs_event1, close_cb); + + uv_run(loop, UV_RUN_DEFAULT); + + ASSERT(close_cb_called == 2); + + remove("watch_dir/"); + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/test/test-list.h b/test/test-list.h index 5f8efda6..d963f04c 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -193,6 +193,7 @@ TEST_DECLARE (fs_event_no_callback_on_close) TEST_DECLARE (fs_event_immediate_close) TEST_DECLARE (fs_event_close_with_pending_event) TEST_DECLARE (fs_event_close_in_callback) +TEST_DECLARE (fs_event_start_and_close) TEST_DECLARE (fs_readdir_empty_dir) TEST_DECLARE (fs_readdir_file) TEST_DECLARE (fs_open_dir) @@ -488,6 +489,7 @@ TASK_LIST_START TEST_ENTRY (fs_event_immediate_close) TEST_ENTRY (fs_event_close_with_pending_event) TEST_ENTRY (fs_event_close_in_callback) + TEST_ENTRY (fs_event_start_and_close) TEST_ENTRY (fs_readdir_empty_dir) TEST_ENTRY (fs_readdir_file) TEST_ENTRY (fs_open_dir)