diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2020-02-17 23:50:59 -0800 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2020-02-17 23:50:59 -0800 |
commit | ceac76daa53fc6f12eab40c2804914dfd503c279 (patch) | |
tree | 433686fdf9ec9041a6063ac69536cc56efffe538 | |
parent | 6d48d0bd1598182c874f1ad5d72b4671944308bb (diff) | |
download | rneovim-ceac76daa53fc6f12eab40c2804914dfd503c279.tar.gz rneovim-ceac76daa53fc6f12eab40c2804914dfd503c279.tar.bz2 rneovim-ceac76daa53fc6f12eab40c2804914dfd503c279.zip |
loop_close: close all handles
- Move uv_stop(), it still causes a "leak" on exit somehow.
- Tenatively restore `UV_RUN_DEFAULT`. It shouldn't hang since we
clobber the handles via `uv_walk((h)=>uv_close(h))`. Although this
still "leaks" on exit, it's faster than the 2-second timeout.
fix #11820
fix #7376
-rw-r--r-- | src/nvim/event/loop.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c index 902b7edc54..e341513ae1 100644 --- a/src/nvim/event/loop.c +++ b/src/nvim/event/loop.c @@ -116,6 +116,15 @@ void loop_on_put(MultiQueue *queue, void *data) uv_stop(&loop->uv); } +#if !defined(EXITFREE) +static void loop_walk_cb(uv_handle_t *handle, void *arg) +{ + if (!uv_is_closing(handle)) { + uv_close(handle, NULL); + } +} +#endif + /// Closes `loop` and its handles, and frees its structures. /// /// @param loop Loop to destroy @@ -125,21 +134,17 @@ void loop_on_put(MultiQueue *queue, void *data) bool loop_close(Loop *loop, bool wait) { bool rv = true; - // Loop won’t block for I/O after this. - uv_stop(&loop->uv); - // TODO(justinmk): Close all (lua/luv!) handles. But walk_cb() needs to call - // the resource-specific close-callbacks... - // uv_walk((h) => { if !uv_is_closing(h) { uv_close(h, …) } }) uv_mutex_destroy(&loop->mutex); uv_close((uv_handle_t *)&loop->children_watcher, NULL); uv_close((uv_handle_t *)&loop->children_kill_timer, NULL); uv_close((uv_handle_t *)&loop->poll_timer, timer_close_cb); uv_close((uv_handle_t *)&loop->async, NULL); uint64_t start = wait ? os_hrtime() : 0; + bool didstop = false; while (true) { // Run the loop to tickle close-callbacks (which should then free memory). // Use UV_RUN_NOWAIT to avoid a hang. #11820 - uv_run(&loop->uv, UV_RUN_NOWAIT); + uv_run(&loop->uv, didstop ? UV_RUN_DEFAULT : UV_RUN_NOWAIT); if ((uv_loop_close(&loop->uv) != UV_EBUSY) || !wait) { break; } @@ -151,6 +156,18 @@ bool loop_close(Loop *loop, bool wait) log_uv_handles(&loop->uv); break; } +#if defined(EXITFREE) + (void)didstop; +#else + if (!didstop) { + // Loop won’t block for I/O after this. + uv_stop(&loop->uv); + // XXX: Close all (lua/luv!) handles. But loop_walk_cb() does not call + // resource-specific close-callbacks, so this leaks memory... + uv_walk(&loop->uv, loop_walk_cb, NULL); + didstop = true; + } +#endif } multiqueue_free(loop->fast_events); multiqueue_free(loop->thread_events); |