aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/event/loop.c29
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);