mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
jobwait(): fix race if job exits before waiting on it
Problem: If a job exits while waiting on another job, the on_exit handler is queued but f_jobwait() skips it. Solution: Always do process_wait(), so that handlers are run during f_jobwait(). fix #8302 Test case: $ BUSTED_ARGS="--repeat=2000 --no-keep-going" TEST_FILE=test/functional/core/job_spec.lua TEST_FILTER=waiting make functionaltest Failure example (macOS CI): FAILED test/functional/core/job_spec.lua: jobs jobwait will run callbacks while waiting test/functional/core/job_spec.lua:606: Expected objects to be the same. Passed in: (table: 0x1be77c80) { [1] = 'notification' [2] = 'wait' *[3] = { *[1] = 3 } } Expected: (table: 0x1be77d10) { [1] = 'notification' [2] = 'wait' *[3] = { *[1] = 4 } } stack traceback: test/functional/core/job_spec.lua:606: in function <test/functional/core/job_spec.lua:583
This commit is contained in:
parent
a00eb23c27
commit
58318af718
@ -5411,7 +5411,8 @@ jobstop({id}) *jobstop()*
|
|||||||
See |job-control|.
|
See |job-control|.
|
||||||
|
|
||||||
jobwait({ids}[, {timeout}]) *jobwait()*
|
jobwait({ids}[, {timeout}]) *jobwait()*
|
||||||
Wait for a set of jobs to complete.
|
Wait for a set of jobs and their |on_exit| handlers to
|
||||||
|
complete.
|
||||||
|
|
||||||
{ids} is a list of |job-id|s to wait for.
|
{ids} is a list of |job-id|s to wait for.
|
||||||
{timeout} is the maximum waiting time in milliseconds, -1
|
{timeout} is the maximum waiting time in milliseconds, -1
|
||||||
@ -5427,10 +5428,10 @@ jobwait({ids}[, {timeout}]) *jobwait()*
|
|||||||
Returns a list of len({ids}) integers, where each integer is
|
Returns a list of len({ids}) integers, where each integer is
|
||||||
the wait-result of the corresponding job. Each wait-result is
|
the wait-result of the corresponding job. Each wait-result is
|
||||||
one of the following:
|
one of the following:
|
||||||
* Exit-code, if the job exited
|
Exit-code, if the job exited
|
||||||
* -1 if the timeout was exceeded
|
-1 if the timeout was exceeded
|
||||||
* -2 if the job was interrupted
|
-2 if the job was interrupted (by |CTRL-C|)
|
||||||
* -3 if the |job-id| is invalid
|
-3 if the job-id is invalid
|
||||||
|
|
||||||
join({list} [, {sep}]) *join()*
|
join({list} [, {sep}]) *join()*
|
||||||
Join the items in {list} together into one String.
|
Join the items in {list} together into one String.
|
||||||
|
@ -12487,7 +12487,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if the job already exited, but wasn't freed yet
|
// if the job already exited, but wasn't freed yet
|
||||||
if (jobs[i] == NULL || jobs[i]->stream.proc.status >= 0) {
|
if (jobs[i] == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,7 +607,6 @@ describe('jobs', function()
|
|||||||
\ ])
|
\ ])
|
||||||
call rpcnotify(g:channel, 'wait', sort(g:jobs), sort(g:exits))
|
call rpcnotify(g:channel, 'wait', sort(g:jobs), sort(g:exits))
|
||||||
]])
|
]])
|
||||||
assert:set_parameter('TableFormatLevel', 1000000)
|
|
||||||
eq({'notification', 'wait',
|
eq({'notification', 'wait',
|
||||||
{{3,4,5,6}, {3,4,5,6}}}, next_msg())
|
{{3,4,5,6}, {3,4,5,6}}}, next_msg())
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user