aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2023-11-21 11:24:30 +0000
committerLewis Russell <me@lewisr.dev>2023-11-27 09:09:21 +0000
commit84bbe4b0ca935db1f6202db339aee5594a3b3908 (patch)
treef71a1a2d3ab75f1b1deece31065e80c46b1b842e
parent6343d414369de1f3b259e51438cd4f666d82d3d2 (diff)
downloadrneovim-84bbe4b0ca935db1f6202db339aee5594a3b3908.tar.gz
rneovim-84bbe4b0ca935db1f6202db339aee5594a3b3908.tar.bz2
rneovim-84bbe4b0ca935db1f6202db339aee5594a3b3908.zip
fix(lua): disallow vim.wait() in fast contexts
`vim.wait()` cannot be called in a fast callback since the main loop cannot be run in that context as it is not reentrant Fixes #26122
-rw-r--r--runtime/doc/lua.txt8
-rw-r--r--runtime/doc/news.txt2
-rw-r--r--runtime/lua/vim/_editor.lua3
-rw-r--r--runtime/lua/vim/_meta/builtin.lua4
-rw-r--r--src/nvim/lua/executor.c7
-rw-r--r--test/functional/lua/vim_spec.lua13
6 files changed, 29 insertions, 8 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index a79b26dfb0..a35d70cae8 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1143,6 +1143,8 @@ vim.wait({time}, {callback}, {interval}, {fast_only}) *vim.wait()*
milliseconds (default 200). Nvim still processes other events during this
time.
+ Cannot be called while in an |api-fast| event.
+
Examples: >lua
---
-- Wait for 100 ms, allowing other events to process
@@ -1173,8 +1175,7 @@ vim.wait({time}, {callback}, {interval}, {fast_only}) *vim.wait()*
• {interval} (integer|nil) (Approximate) number of milliseconds to
wait between polls
• {fast_only} (boolean|nil) If true, only |api-fast| events will be
- processed. If called from while in an |api-fast| event,
- will automatically be set to `true`.
+ processed.
Return: ~
boolean, nil|-1|-2
@@ -1828,7 +1829,8 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
• pid (integer) Process ID
• wait (fun(timeout: integer|nil): SystemCompleted) Wait for the
process to complete. Upon timeout the process is sent the KILL
- signal (9) and the exit code is set to 124.
+ signal (9) and the exit code is set to 124. Cannot be called in
+ |api-fast|.
• SystemCompleted is an object with the fields:
• code: (integer)
• signal: (integer)
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index b5bef13325..825e5ba41f 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -325,6 +325,8 @@ The following changes to existing APIs or features add new behavior.
NOTE: the regexp engine still has a hard-coded limit of considering
6 composing chars only.
+• |vim.wait()| is no longer allowed to be called in |api-fast|.
+
==============================================================================
REMOVED FEATURES *news-removed*
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index 12b632075d..6cccbe8313 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -124,7 +124,8 @@ vim.log = {
--- @return vim.SystemObj Object with the fields:
--- - pid (integer) Process ID
--- - wait (fun(timeout: integer|nil): SystemCompleted) Wait for the process to complete. Upon
---- timeout the process is sent the KILL signal (9) and the exit code is set to 124.
+--- timeout the process is sent the KILL signal (9) and the exit code is set to 124. Cannot
+--- be called in |api-fast|.
--- - SystemCompleted is an object with the fields:
--- - code: (integer)
--- - signal: (integer)
diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua
index 92c23f7764..eeba356672 100644
--- a/runtime/lua/vim/_meta/builtin.lua
+++ b/runtime/lua/vim/_meta/builtin.lua
@@ -205,6 +205,8 @@ function vim.schedule(fn) end
--- milliseconds (default 200). Nvim still processes other events during
--- this time.
---
+--- Cannot be called while in an |api-fast| event.
+---
--- Examples:
---
--- ```lua
@@ -235,8 +237,6 @@ function vim.schedule(fn) end
--- @param callback? fun(): boolean Optional callback. Waits until {callback} returns true
--- @param interval? integer (Approximate) number of milliseconds to wait between polls
--- @param fast_only? boolean If true, only |api-fast| events will be processed.
---- If called from while in an |api-fast| event, will
---- automatically be set to `true`.
--- @return boolean, nil|-1|-2
--- - If {callback} returns `true` during the {time}: `true, nil`
--- - If {callback} never returns `true` during the {time}: `false, -1`
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index ce2a247a6f..04eda99d17 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -411,6 +411,10 @@ static bool nlua_wait_condition(lua_State *lstate, int *status, bool *callback_r
static int nlua_wait(lua_State *lstate)
FUNC_ATTR_NONNULL_ALL
{
+ if (in_fast_callback) {
+ return luaL_error(lstate, e_luv_api_disabled, "vim.wait");
+ }
+
intptr_t timeout = luaL_checkinteger(lstate, 1);
if (timeout < 0) {
return luaL_error(lstate, "timeout must be >= 0");
@@ -449,8 +453,7 @@ static int nlua_wait(lua_State *lstate)
fast_only = lua_toboolean(lstate, 4);
}
- MultiQueue *loop_events = fast_only || in_fast_callback > 0
- ? main_loop.fast_events : main_loop.events;
+ MultiQueue *loop_events = fast_only ? main_loop.fast_events : main_loop.events;
TimeWatcher *tw = xmalloc(sizeof(TimeWatcher));
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 1533a1823f..61fa16f59d 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -2769,6 +2769,19 @@ describe('lua stdlib', function()
eq({'notification', 'wait', {-2}}, next_msg(500))
end)
end)
+
+ it('should not run in fast callbacks #26122', function()
+ exec_lua([[
+ vim.uv.new_timer():start(0, 100, function()
+ local count = 0
+ vim.wait(100, function()
+ count = count + 1
+ return count == 10
+ end, 100)
+ end)
+ ]])
+ assert_alive()
+ end)
end)
it('vim.notify_once', function()