aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lua/executor.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2026-02-13 21:02:40 +0800
committerGitHub <noreply@github.com>2026-02-13 21:02:40 +0800
commit9c5ade9212d897db590aeb6a2a5340e73ffe44d0 (patch)
treee80e7276533523f7a204e4810f141afc83c15865 /src/nvim/lua/executor.c
parenta7a7cdbcda1f0ef5a29742aea973d2d1c0bfa9a0 (diff)
downloadrneovim-9c5ade9212d897db590aeb6a2a5340e73ffe44d0.tar.gz
rneovim-9c5ade9212d897db590aeb6a2a5340e73ffe44d0.tar.bz2
rneovim-9c5ade9212d897db590aeb6a2a5340e73ffe44d0.zip
fix: wait() checks condition twice on each interval (#37837)
Problem: wait() checks condition twice on each interval. Solution: Don't schedule the due callback. Also fix memory leak when Nvim exits while waiting. No test that the condition isn't checked twice, as testing for that can be flaky when there are libuv events from other sources.
Diffstat (limited to 'src/nvim/lua/executor.c')
-rw-r--r--src/nvim/lua/executor.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index b76244cc2d..93a4fa574a 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -423,12 +423,18 @@ static int nlua_schedule(lua_State *const lstate)
return 2;
}
-// Dummy timer callback. Used by f_wait().
+// Dummy timer callback. Used by vim.wait().
static void dummy_timer_due_cb(TimeWatcher *tw, void *data)
{
+ // If the main loop is closing, the condition won't be checked again.
+ // Close the timer to avoid leaking resources.
+ if (main_loop.closing) {
+ time_watcher_stop(tw);
+ time_watcher_close(tw, dummy_timer_close_cb);
+ }
}
-// Dummy timer close callback. Used by f_wait().
+// Dummy timer close callback. Used by vim.wait().
static void dummy_timer_close_cb(TimeWatcher *tw, void *data)
{
xfree(tw);
@@ -512,12 +518,10 @@ static int nlua_wait(lua_State *lstate)
// Start dummy timer.
time_watcher_init(&main_loop, tw, NULL);
- tw->events = loop_events;
- tw->blockable = true;
- time_watcher_start(tw,
- dummy_timer_due_cb,
- (uint64_t)interval,
- (uint64_t)interval);
+ // Don't schedule the due callback, as that'll lead to two different types of events
+ // on each interval, causing the condition to be checked twice.
+ tw->events = NULL;
+ time_watcher_start(tw, dummy_timer_due_cb, (uint64_t)interval, (uint64_t)interval);
int pcall_status = 0;
bool callback_result = false;