Skip to content

Commit b022600

Browse files
jeffhostetlergitster
authored andcommitted
fsmonitor: eliminate call to deprecated FSEventStream function
Replace the call to `FSEventStreamScheduleWithRunLoop()` function with the suggested `FSEventStreamSetDispatchQueue()` function. The MacOS version of the builtin FSMonitor feature uses the `FSEventStreamScheduleWithRunLoop()` function to drive the event loop and process FSEvents from the system. This routine has now been deprecated by Apple. The MacOS 13 (Ventura) compiler tool chain now generates a warning when compiling calls to this function. In DEVELOPER=1 mode, this now causes a compile error. The `FSEventStreamSetDispatchQueue()` function is conceptually similar and is the suggested replacement. However, there are some subtle thread-related differences. Previously, the event stream would be processed by the `fsm_listen__loop()` thread while it was in the `CFRunLoopRun()` method. (Conceptually, this was a blocking call on the lifetime of the event stream where our thread drove the event loop and individual events were handled by the `fsevent_callback()`.) With the change, a "dispatch queue" is created and FSEvents will be processed by a hidden queue-related thread (that calls the `fsevent_callback()` on our behalf). Our `fsm_listen__loop()` thread maintains the original blocking model by waiting on a mutex/condition variable pair while the hidden thread does all of the work. While the deprecated API used by the original were introduced in macOS 10.5 (Oct 2007), the API used by the updated code were introduced back in macOS 10.6 (Aug 2009) and has been available since then. So this change _could_ break those who have happily been using 10.5 (if there were such people), but these two dates both predate the oldest versions of macOS Apple seems to support anyway, so we should be safe. Signed-off-by: Jeff Hostetler <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e7e5c6f commit b022600

File tree

2 files changed

+25
-14
lines changed

2 files changed

+25
-14
lines changed

compat/fsmonitor/fsm-darwin-gcc.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,7 @@ void CFRunLoopRun(void);
8080
void CFRunLoopStop(CFRunLoopRef run_loop);
8181
CFRunLoopRef CFRunLoopGetCurrent(void);
8282
extern CFStringRef kCFRunLoopDefaultMode;
83-
void FSEventStreamScheduleWithRunLoop(FSEventStreamRef stream,
84-
CFRunLoopRef run_loop,
85-
CFStringRef run_loop_mode);
83+
void FSEventStreamSetDispatchQueue(FSEventStreamRef stream, dispatch_queue_t q);
8684
unsigned char FSEventStreamStart(FSEventStreamRef stream);
8785
void FSEventStreamStop(FSEventStreamRef stream);
8886
void FSEventStreamInvalidate(FSEventStreamRef stream);

compat/fsmonitor/fsm-listen-darwin.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#ifndef __clang__
2+
#include <dispatch/dispatch.h>
23
#include "fsm-darwin-gcc.h"
34
#else
45
#include <CoreFoundation/CoreFoundation.h>
@@ -37,7 +38,9 @@ struct fsm_listen_data
3738

3839
FSEventStreamRef stream;
3940

40-
CFRunLoopRef rl;
41+
dispatch_queue_t dq;
42+
pthread_cond_t dq_finished;
43+
pthread_mutex_t dq_lock;
4144

4245
enum shutdown_style {
4346
SHUTDOWN_EVENT = 0,
@@ -369,8 +372,11 @@ static void fsevent_callback(ConstFSEventStreamRef streamRef,
369372
fsmonitor_batch__free_list(batch);
370373
string_list_clear(&cookie_list, 0);
371374

375+
pthread_mutex_lock(&data->dq_lock);
372376
data->shutdown_style = FORCE_SHUTDOWN;
373-
CFRunLoopStop(data->rl);
377+
pthread_cond_broadcast(&data->dq_finished);
378+
pthread_mutex_unlock(&data->dq_lock);
379+
374380
strbuf_release(&tmp);
375381
return;
376382
}
@@ -431,10 +437,6 @@ int fsm_listen__ctor(struct fsmonitor_daemon_state *state)
431437
if (!data->stream)
432438
goto failed;
433439

434-
/*
435-
* `data->rl` needs to be set inside the listener thread.
436-
*/
437-
438440
return 0;
439441

440442
failed:
@@ -461,6 +463,11 @@ void fsm_listen__dtor(struct fsmonitor_daemon_state *state)
461463
FSEventStreamRelease(data->stream);
462464
}
463465

466+
if (data->dq)
467+
dispatch_release(data->dq);
468+
pthread_cond_destroy(&data->dq_finished);
469+
pthread_mutex_destroy(&data->dq_lock);
470+
464471
FREE_AND_NULL(state->listen_data);
465472
}
466473

@@ -469,9 +476,11 @@ void fsm_listen__stop_async(struct fsmonitor_daemon_state *state)
469476
struct fsm_listen_data *data;
470477

471478
data = state->listen_data;
472-
data->shutdown_style = SHUTDOWN_EVENT;
473479

474-
CFRunLoopStop(data->rl);
480+
pthread_mutex_lock(&data->dq_lock);
481+
data->shutdown_style = SHUTDOWN_EVENT;
482+
pthread_cond_broadcast(&data->dq_finished);
483+
pthread_mutex_unlock(&data->dq_lock);
475484
}
476485

477486
void fsm_listen__loop(struct fsmonitor_daemon_state *state)
@@ -480,9 +489,11 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state)
480489

481490
data = state->listen_data;
482491

483-
data->rl = CFRunLoopGetCurrent();
492+
pthread_mutex_init(&data->dq_lock, NULL);
493+
pthread_cond_init(&data->dq_finished, NULL);
494+
data->dq = dispatch_queue_create("FSMonitor", NULL);
484495

485-
FSEventStreamScheduleWithRunLoop(data->stream, data->rl, kCFRunLoopDefaultMode);
496+
FSEventStreamSetDispatchQueue(data->stream, data->dq);
486497
data->stream_scheduled = 1;
487498

488499
if (!FSEventStreamStart(data->stream)) {
@@ -491,7 +502,9 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state)
491502
}
492503
data->stream_started = 1;
493504

494-
CFRunLoopRun();
505+
pthread_mutex_lock(&data->dq_lock);
506+
pthread_cond_wait(&data->dq_finished, &data->dq_lock);
507+
pthread_mutex_unlock(&data->dq_lock);
495508

496509
switch (data->shutdown_style) {
497510
case FORCE_ERROR_STOP:

0 commit comments

Comments
 (0)