aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/edit.c4
-rw-r--r--src/nvim/event/loop.c36
-rw-r--r--src/nvim/marktree.c3
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;
}
}