summaryrefslogtreecommitdiffstats
path: root/Utilities/cmlibuv/src/unix/linux-inotify.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibuv/src/unix/linux-inotify.c')
-rw-r--r--Utilities/cmlibuv/src/unix/linux-inotify.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/Utilities/cmlibuv/src/unix/linux-inotify.c b/Utilities/cmlibuv/src/unix/linux-inotify.c
index 4708c05..5934c5d 100644
--- a/Utilities/cmlibuv/src/unix/linux-inotify.c
+++ b/Utilities/cmlibuv/src/unix/linux-inotify.c
@@ -61,6 +61,8 @@ static void uv__inotify_read(uv_loop_t* loop,
uv__io_t* w,
unsigned int revents);
+static void maybe_free_watcher_list(struct watcher_list* w,
+ uv_loop_t* loop);
static int new_inotify_fd(void) {
int err;
@@ -108,6 +110,71 @@ static int init_inotify(uv_loop_t* loop) {
}
+int uv__inotify_fork(uv_loop_t* loop, void* old_watchers) {
+ /* Open the inotify_fd, and re-arm all the inotify watchers. */
+ int err;
+ struct watcher_list* tmp_watcher_list_iter;
+ struct watcher_list* watcher_list;
+ struct watcher_list tmp_watcher_list;
+ QUEUE queue;
+ QUEUE* q;
+ uv_fs_event_t* handle;
+ char* tmp_path;
+
+ if (old_watchers != NULL) {
+ /* We must restore the old watcher list to be able to close items
+ * out of it.
+ */
+ loop->inotify_watchers = old_watchers;
+
+ QUEUE_INIT(&tmp_watcher_list.watchers);
+ /* Note that the queue we use is shared with the start and stop()
+ * functions, making QUEUE_FOREACH unsafe to use. So we use the
+ * QUEUE_MOVE trick to safely iterate. Also don't free the watcher
+ * list until we're done iterating. c.f. uv__inotify_read.
+ */
+ RB_FOREACH_SAFE(watcher_list, watcher_root,
+ CAST(&old_watchers), tmp_watcher_list_iter) {
+ watcher_list->iterating = 1;
+ QUEUE_MOVE(&watcher_list->watchers, &queue);
+ while (!QUEUE_EMPTY(&queue)) {
+ q = QUEUE_HEAD(&queue);
+ handle = QUEUE_DATA(q, uv_fs_event_t, watchers);
+ /* It's critical to keep a copy of path here, because it
+ * will be set to NULL by stop() and then deallocated by
+ * maybe_free_watcher_list
+ */
+ tmp_path = uv__strdup(handle->path);
+ assert(tmp_path != NULL);
+ QUEUE_REMOVE(q);
+ QUEUE_INSERT_TAIL(&watcher_list->watchers, q);
+ uv_fs_event_stop(handle);
+
+ QUEUE_INSERT_TAIL(&tmp_watcher_list.watchers, &handle->watchers);
+ handle->path = tmp_path;
+ }
+ watcher_list->iterating = 0;
+ maybe_free_watcher_list(watcher_list, loop);
+ }
+
+ QUEUE_MOVE(&tmp_watcher_list.watchers, &queue);
+ while (!QUEUE_EMPTY(&queue)) {
+ q = QUEUE_HEAD(&queue);
+ QUEUE_REMOVE(q);
+ handle = QUEUE_DATA(q, uv_fs_event_t, watchers);
+ tmp_path = handle->path;
+ handle->path = NULL;
+ err = uv_fs_event_start(handle, handle->cb, tmp_path, 0);
+ uv__free(tmp_path);
+ if (err)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+
static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) {
struct watcher_list w;
w.wd = wd;