summaryrefslogtreecommitdiffstats
path: root/Utilities/cmlibuv/src/unix/kqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibuv/src/unix/kqueue.c')
-rw-r--r--Utilities/cmlibuv/src/unix/kqueue.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c
index fffd462..6bc60bb 100644
--- a/Utilities/cmlibuv/src/unix/kqueue.c
+++ b/Utilities/cmlibuv/src/unix/kqueue.c
@@ -48,6 +48,37 @@ int uv__kqueue_init(uv_loop_t* loop) {
}
+static int uv__has_forked_with_cfrunloop;
+
+int uv__io_fork(uv_loop_t* loop) {
+ int err;
+ uv__close(loop->backend_fd);
+ loop->backend_fd = -1;
+ err = uv__kqueue_init(loop);
+ if (err)
+ return err;
+
+#if defined(__APPLE__)
+ if (loop->cf_state != NULL) {
+ /* We cannot start another CFRunloop and/or thread in the child
+ process; CF aborts if you try or if you try to touch the thread
+ at all to kill it. So the best we can do is ignore it from now
+ on. This means we can't watch directories in the same way
+ anymore (like other BSDs). It also means we cannot properly
+ clean up the allocated resources; calling
+ uv__fsevents_loop_delete from uv_loop_close will crash the
+ process. So we sidestep the issue by pretending like we never
+ started it in the first place.
+ */
+ uv__has_forked_with_cfrunloop = 1;
+ uv__free(loop->cf_state);
+ loop->cf_state = NULL;
+ }
+#endif
+ return err;
+}
+
+
int uv__io_check_fd(uv_loop_t* loop, int fd) {
struct kevent ev;
int rc;
@@ -404,6 +435,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
handle->cb = cb;
#if defined(__APPLE__)
+ if (uv__has_forked_with_cfrunloop)
+ goto fallback;
+
/* Nullify field to perform checks later */
handle->cf_cb = NULL;
handle->realpath = NULL;
@@ -438,7 +472,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
uv__handle_stop(handle);
#if defined(__APPLE__)
- if (uv__fsevents_close(handle))
+ if (uv__has_forked_with_cfrunloop || uv__fsevents_close(handle))
#endif /* defined(__APPLE__) */
{
uv__io_close(handle->loop, &handle->event_watcher);