fix(jobs): do not block UI when jobwait() doesn't block (#31803)

(cherry picked from commit efe1732c6f)
This commit is contained in:
Gregory Anders
2025-01-01 18:43:16 -06:00
committed by github-actions[bot]
parent 6a6c6b2658
commit 357ee88606
2 changed files with 44 additions and 3 deletions

View File

@ -4562,8 +4562,6 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
ui_busy_start();
ui_flush();
list_T *args = argvars[0].vval.v_list;
Channel **jobs = xcalloc((size_t)tv_list_len(args), sizeof(*jobs));
MultiQueue *waiting_jobs = multiqueue_new_parent(loop_on_put, &main_loop);
@ -4600,6 +4598,13 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
before = os_hrtime();
}
// Only mark the UI as busy when jobwait() blocks
const bool busy = remaining != 0;
if (busy) {
ui_busy_start();
ui_flush();
}
for (i = 0; i < tv_list_len(args); i++) {
if (remaining == 0) {
break; // Timeout.
@ -4641,7 +4646,9 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
multiqueue_free(waiting_jobs);
xfree(jobs);
ui_busy_stop();
if (busy) {
ui_busy_stop();
}
tv_list_ref(rv);
rettv->v_type = VAR_LIST;
rettv->vval.v_list = rv;

View File

@ -943,6 +943,40 @@ describe('jobs', function()
feed('<CR>')
fn.jobstop(api.nvim_get_var('id'))
end)
it('does not set UI busy with zero timeout #31712', function()
local screen = Screen.new(50, 6)
screen:attach()
command([[let g:id = jobstart(['sleep', '0.3'])]])
local busy = 0
screen._handle_busy_start = (function(orig)
return function()
orig(screen)
busy = busy + 1
end
end)(screen._handle_busy_start)
source([[
func PrintAndPoll()
echon "aaa\nbbb"
call jobwait([g:id], 0)
echon "\nccc"
endfunc
]])
feed_command('call PrintAndPoll()')
screen:expect {
grid = [[
|
{3: }|
aaa |
bbb |
ccc |
{6:Press ENTER or type command to continue}^ |
]],
}
feed('<CR>')
fn.jobstop(api.nvim_get_var('id'))
eq(0, busy)
end)
end)
pending('exit event follows stdout, stderr', function()