diff options
author | Saúl Ibarra Corretgé <saghul@gmail.com> | 2015-12-13 12:07:04 +0100 |
---|---|---|
committer | Saúl Ibarra Corretgé <saghul@gmail.com> | 2015-12-14 21:53:42 +0100 |
commit | 69b94ec55cb0f8bd90475b5b7dabd57beb7e7dfe (patch) | |
tree | d2afb35396d77e45647e1818357a7e17b2be2244 /deps/uv/src/unix/linux-inotify.c | |
parent | e0bb118a1d5f8b6b1eb2405f2dc19b8118f8ec0e (diff) | |
download | android-node-v8-69b94ec55cb0f8bd90475b5b7dabd57beb7e7dfe.tar.gz android-node-v8-69b94ec55cb0f8bd90475b5b7dabd57beb7e7dfe.tar.bz2 android-node-v8-69b94ec55cb0f8bd90475b5b7dabd57beb7e7dfe.zip |
deps: upgrade libuv to 1.8.0
Fixes: https://github.com/nodejs/node/issues/3718
PR-URL: https://github.com/nodejs/node/pull/4276
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/uv/src/unix/linux-inotify.c')
-rw-r--r-- | deps/uv/src/unix/linux-inotify.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c index d9ed9f4b24..282912115d 100644 --- a/deps/uv/src/unix/linux-inotify.c +++ b/deps/uv/src/unix/linux-inotify.c @@ -35,6 +35,7 @@ struct watcher_list { RB_ENTRY(watcher_list) entry; QUEUE watchers; + int iterating; char* path; int wd; }; @@ -113,6 +114,15 @@ static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) { return RB_FIND(watcher_root, CAST(&loop->inotify_watchers), &w); } +static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) { + /* if the watcher_list->watchers is being iterated over, we can't free it. */ + if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) { + /* No watchers left for this path. Clean up. */ + RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w); + uv__inotify_rm_watch(loop->inotify_fd, w->wd); + uv__free(w); + } +} static void uv__inotify_read(uv_loop_t* loop, uv__io_t* dummy, @@ -120,6 +130,7 @@ static void uv__inotify_read(uv_loop_t* loop, const struct uv__inotify_event* e; struct watcher_list* w; uv_fs_event_t* h; + QUEUE queue; QUEUE* q; const char* path; ssize_t size; @@ -159,10 +170,31 @@ static void uv__inotify_read(uv_loop_t* loop, */ path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); - QUEUE_FOREACH(q, &w->watchers) { + /* We're about to iterate over the queue and call user's callbacks. + * What can go wrong? + * A callback could call uv_fs_event_stop() + * and the queue can change under our feet. + * So, we use QUEUE_MOVE() trick to safely iterate over the queue. + * And we don't free the watcher_list until we're done iterating. + * + * First, + * tell uv_fs_event_stop() (that could be called from a user's callback) + * not to free watcher_list. + */ + w->iterating = 1; + QUEUE_MOVE(&w->watchers, &queue); + while (!QUEUE_EMPTY(&queue)) { + q = QUEUE_HEAD(&queue); h = QUEUE_DATA(q, uv_fs_event_t, watchers); + + QUEUE_REMOVE(q); + QUEUE_INSERT_TAIL(&w->watchers, q); + h->cb(h, path, events, 0); } + /* done iterating, time to (maybe) free empty watcher_list */ + w->iterating = 0; + maybe_free_watcher_list(w, loop); } } } @@ -214,6 +246,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, w->wd = wd; w->path = strcpy((char*)(w + 1), path); QUEUE_INIT(&w->watchers); + w->iterating = 0; RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w); no_insert: @@ -241,12 +274,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { uv__handle_stop(handle); QUEUE_REMOVE(&handle->watchers); - if (QUEUE_EMPTY(&w->watchers)) { - /* No watchers left for this path. Clean up. */ - RB_REMOVE(watcher_root, CAST(&handle->loop->inotify_watchers), w); - uv__inotify_rm_watch(handle->loop->inotify_fd, w->wd); - uv__free(w); - } + maybe_free_watcher_list(w, handle->loop); return 0; } |