diff options
-rw-r--r-- | src/nvim/edit.c | 4 | ||||
-rw-r--r-- | src/nvim/event/loop.c | 36 | ||||
-rw-r--r-- | src/nvim/marktree.c | 3 |
3 files changed, 35 insertions, 8 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c index cebd08af28..3e57bc8599 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -574,10 +574,8 @@ static int insert_check(VimState *state) foldCheckClose(); } - int cmdchar_todo = s->cmdchar; if (bt_prompt(curbuf)) { - init_prompt(cmdchar_todo); - cmdchar_todo = NUL; + init_prompt(s->cmdchar); } // If we inserted a character at the last position of the last line in the diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c index 664f3ad89d..e341513ae1 100644 --- a/src/nvim/event/loop.c +++ b/src/nvim/event/loop.c @@ -116,6 +116,20 @@ 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 +/// @param wait Wait briefly for handles to deref +/// /// @returns false if the loop could not be closed gracefully bool loop_close(Loop *loop, bool wait) { @@ -126,18 +140,34 @@ bool loop_close(Loop *loop, bool wait) 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) { - uv_run(&loop->uv, UV_RUN_NOWAIT); - if (!wait || (uv_loop_close(&loop->uv) != UV_EBUSY)) { + // 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, didstop ? UV_RUN_DEFAULT : UV_RUN_NOWAIT); + if ((uv_loop_close(&loop->uv) != UV_EBUSY) || !wait) { break; } - if (os_hrtime() - start >= 2 * 1000000000) { + uint64_t elapsed_s = (os_hrtime() - start) / 1000000000; // seconds + if (elapsed_s >= 2) { // Some libuv resource was not correctly deref'd. Log and bail. rv = false; ELOG("uv_loop_close() hang?"); 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); diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c index 52e602cd94..25b07366d7 100644 --- a/src/nvim/marktree.c +++ b/src/nvim/marktree.c @@ -197,7 +197,7 @@ static inline void split_node(MarkTree *b, mtnode_t *x, const int i) // x must not be a full node (even if there might be internal space) static inline void marktree_putp_aux(MarkTree *b, mtnode_t *x, mtkey_t k) { - int i = x->n - 1; + int i; if (x->level == 0) { i = marktree_getp_aux(x, k, 0); if (i != x->n - 1) { @@ -905,7 +905,6 @@ continue_same_node: refkey(b, itr->node, itr->i); refkey(b, enditr->node, enditr->i); } else { - past_right = true; break; } } |