From 55defa1a41baac65cd32dc499b330af9751d6c5b Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Mon, 16 Aug 2021 21:06:49 -0600 Subject: fix(terminal): close without ! if the job is stopped - If the terminal job is still running then ! is still required. Closes #4683 --- src/nvim/buffer.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index fdb3ffdc7e..81f8b9073e 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1218,8 +1218,8 @@ do_buffer( return FAIL; } - if (!forceit && (buf->terminal || bufIsChanged(buf))) { - if ((p_confirm || cmdmod.confirm) && p_write && !buf->terminal) { + if (!forceit && bufIsChanged(buf)) { + if ((p_confirm || cmdmod.confirm) && p_write) { dialog_changed(buf, false); if (!bufref_valid(&bufref)) { // Autocommand deleted buffer, oops! It's not changed now. @@ -1231,22 +1231,22 @@ do_buffer( return FAIL; } } else { - if (buf->terminal) { - if (p_confirm || cmdmod.confirm) { - if (!dialog_close_terminal(buf)) { - return FAIL; - } - } else { - EMSG2(_("E89: %s will be killed (add ! to override)"), - (char *)buf->b_fname); - return FAIL; - } - } else { - EMSGN(_("E89: No write since last change for buffer %" PRId64 - " (add ! to override)"), - buf->b_fnum); + EMSGN(_("E89: No write since last change for buffer %" PRId64 + " (add ! to override)"), + buf->b_fnum); + return FAIL; + } + } + + if (!forceit && buf->terminal && terminal_running(buf->terminal)) { + if (p_confirm || cmdmod.confirm) { + if (!dialog_close_terminal(buf)) { return FAIL; } + } else { + EMSG2(_("E89: %s will be killed (add ! to override)"), + (char *)buf->b_fname); + return FAIL; } } -- cgit From 3c081d028062f793b63b8689f854bbea30e15752 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Sat, 28 Aug 2021 09:58:27 -0600 Subject: fix(jobwait): always drain process event queues #15402 Problem: jobwait() returns early if the job was stopped, but the job might have pending callbacks on its event queue which are required to complete its teardown. State such as term->closed might not be updated yet (by the pending callbacks), so codepaths such as :bdelete think the job is still running. Solution: Always flush the job's event queue before returning from jobwait(). ref #15349 --- src/nvim/eval/funcs.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8a1258efd4..99f9f17e0a 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5404,14 +5404,19 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) TV_LIST_ITER_CONST(args, arg, { Channel *chan = NULL; if (TV_LIST_ITEM_TV(arg)->v_type != VAR_NUMBER - || !(chan = find_job(TV_LIST_ITEM_TV(arg)->vval.v_number, false))) { + || !(chan = find_channel(TV_LIST_ITEM_TV(arg)->vval.v_number)) + || chan->streamtype != kChannelStreamProc) { + jobs[i] = NULL; // Invalid job. + } else if (process_is_stopped(&chan->stream.proc)) { + // Job is stopped but not fully destroyed. + // Ensure all callbacks on its event queue are executed. #15402 + process_wait(&chan->stream.proc, -1, NULL); jobs[i] = NULL; // Invalid job. } else { jobs[i] = chan; channel_incref(chan); if (chan->stream.proc.status < 0) { - // Process any pending events on the job's queue before temporarily - // replacing it. + // Flush any events in the job's queue before temporarily replacing it. multiqueue_process_events(chan->events); multiqueue_replace_parent(chan->events, waiting_jobs); } -- cgit