Skip to content
This repository was archived by the owner on May 4, 2018. It is now read-only.

Commit ea4cb77

Browse files
committed
fsevents: FSEvents is most likely not thread-safe
Perform all operation with FSEventStream in the same thread, where it'll be used. Conflicts: src/unix/fsevents.c
1 parent 9bae606 commit ea4cb77

File tree

2 files changed

+64
-45
lines changed

2 files changed

+64
-45
lines changed

src/unix/fsevents.c

+63-45
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,67 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
212212

213213
static void uv__fsevents_schedule(void* arg) {
214214
uv_fs_event_t* handle;
215+
FSEventStreamContext ctx;
216+
FSEventStreamRef ref;
217+
CFStringRef path;
218+
CFArrayRef paths;
219+
CFAbsoluteTime latency;
220+
FSEventStreamCreateFlags flags;
215221

216222
handle = arg;
223+
224+
/* Initialize context */
225+
ctx.version = 0;
226+
ctx.info = handle;
227+
ctx.retain = NULL;
228+
ctx.release = NULL;
229+
ctx.copyDescription = NULL;
230+
231+
/* Initialize paths array */
232+
path = CFStringCreateWithCString(NULL,
233+
handle->filename,
234+
CFStringGetSystemEncoding());
235+
assert(path != NULL);
236+
paths = CFArrayCreate(NULL, (const void**)&path, 1, NULL);
237+
assert(paths != NULL);
238+
239+
latency = 0.15;
240+
241+
/* Set appropriate flags */
242+
flags = kFSEventStreamCreateFlagFileEvents;
243+
244+
ref = FSEventStreamCreate(NULL,
245+
&uv__fsevents_event_cb,
246+
&ctx,
247+
paths,
248+
kFSEventStreamEventIdSinceNow,
249+
latency,
250+
flags);
251+
assert(ref != NULL);
252+
handle->cf_eventstream = ref;
253+
217254
FSEventStreamScheduleWithRunLoop(handle->cf_eventstream,
218255
handle->loop->cf_loop,
219256
kCFRunLoopDefaultMode);
220-
FSEventStreamStart(handle->cf_eventstream);
257+
if (!FSEventStreamStart(handle->cf_eventstream))
258+
abort();
259+
}
260+
261+
262+
static void uv__fsevents_unschedule(void* arg) {
263+
uv_fs_event_t* handle;
264+
265+
handle = arg;
266+
267+
/* Stop emitting events */
268+
FSEventStreamStop(handle->cf_eventstream);
269+
270+
/* Release stream */
271+
FSEventStreamInvalidate(handle->cf_eventstream);
272+
FSEventStreamRelease(handle->cf_eventstream);
273+
handle->cf_eventstream = NULL;
274+
275+
/* Notify main thread that we're done here */
221276
uv_sem_post(&handle->cf_sem);
222277
}
223278

@@ -357,50 +412,18 @@ void uv__cf_loop_signal(uv_loop_t* loop, cf_loop_signal_cb cb, void* arg) {
357412

358413

359414
int uv__fsevents_init(uv_fs_event_t* handle) {
360-
FSEventStreamContext ctx;
361-
FSEventStreamRef ref;
362-
CFStringRef path;
363-
CFArrayRef paths;
364-
CFAbsoluteTime latency;
365-
FSEventStreamCreateFlags flags;
366415
int err;
367416

368417
err = uv__fsevents_loop_init(handle->loop);
369418
if (err)
370419
return err;
371420

372-
/* Initialize context */
373-
ctx.version = 0;
374-
ctx.info = handle;
375-
ctx.retain = NULL;
376-
ctx.release = NULL;
377-
ctx.copyDescription = NULL;
378-
379421
/* Get absolute path to file */
380422
handle->realpath = realpath(handle->filename, NULL);
381423
if (handle->realpath != NULL)
382424
handle->realpath_len = strlen(handle->realpath);
383425

384-
/* Initialize paths array */
385-
path = CFStringCreateWithCString(NULL,
386-
handle->filename,
387-
CFStringGetSystemEncoding());
388-
paths = CFArrayCreate(NULL, (const void**)&path, 1, NULL);
389-
390-
latency = 0.15;
391-
392-
/* Set appropriate flags */
393-
flags = kFSEventStreamCreateFlagFileEvents;
394-
395-
ref = FSEventStreamCreate(NULL,
396-
&uv__fsevents_event_cb,
397-
&ctx,
398-
paths,
399-
kFSEventStreamEventIdSinceNow,
400-
latency,
401-
flags);
402-
handle->cf_eventstream = ref;
403-
426+
handle->cf_eventstream = NULL;
404427
/*
405428
* Events will occur in other thread.
406429
* Initialize callback for getting them back into event loop's thread
@@ -425,21 +448,16 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
425448

426449

427450
int uv__fsevents_close(uv_fs_event_t* handle) {
428-
if (handle->cf_eventstream == NULL)
429-
return -1;
430-
431-
/* Ensure that event stream was scheduled */
432-
uv_sem_wait(&handle->cf_sem);
451+
if (handle->cf_cb == NULL)
452+
return -EINVAL;
433453

434-
/* Stop emitting events */
435-
FSEventStreamStop(handle->cf_eventstream);
454+
uv__cf_loop_signal(handle->loop, uv__fsevents_unschedule, handle);
436455

437-
/* Release stream */
438-
FSEventStreamInvalidate(handle->cf_eventstream);
439-
FSEventStreamRelease(handle->cf_eventstream);
440-
handle->cf_eventstream = NULL;
456+
/* Wait for deinitialization */
457+
uv_sem_wait(&handle->cf_sem);
441458

442459
uv_close((uv_handle_t*) handle->cf_cb, (uv_close_cb) free);
460+
handle->cf_cb = NULL;
443461

444462
/* Free data in queue */
445463
UV__FSEVENTS_WALK(handle, {

src/unix/kqueue.c

+1
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ int uv_fs_event_init(uv_loop_t* loop,
307307

308308
#if defined(__APPLE__)
309309
/* Nullify field to perform checks later */
310+
handle->cf_cb = NULL;
310311
handle->cf_eventstream = NULL;
311312
handle->realpath = NULL;
312313
handle->realpath_len = 0;

0 commit comments

Comments
 (0)