commit 69a19295f8fe90356011eff2b7fa67b0593fffcc
parent 3bc72a4980ab2ffe0c3c5300b79b93905b0237e3
Author: markstegeman <markstegeman@users.noreply.github.com>
Date: Wed, 12 Mar 2025 13:35:14 +0100
fix(terminal): delay when finishing terminal process #32846
Problem:
On Windows, the first attempt at finishing up after a terminal process
terminates is delayed by 200ms, even if it would be possible to finish
up immediately.
Solution:
Make the first attempt at finishing up immediately after the process
terminates.
Diffstat:
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/src/nvim/os/pty_proc_win.c b/src/nvim/os/pty_proc_win.c
@@ -16,28 +16,40 @@
# include "os/pty_proc_win.c.generated.h"
#endif
-static void CALLBACK pty_proc_finish1(void *context, BOOLEAN unused)
+static void CALLBACK pty_proc_terminate_cb(void *context, BOOLEAN unused)
FUNC_ATTR_NONNULL_ALL
{
PtyProc *ptyproc = (PtyProc *)context;
Proc *proc = (Proc *)ptyproc;
os_conpty_free(ptyproc->conpty);
- // NB: pty_proc_finish1() is called on a separate thread,
- // but the timer only works properly if it's started by the main thread.
- loop_schedule_fast(proc->loop, event_create(start_wait_eof_timer, ptyproc));
+ // NB: pty_proc_terminate_cb() is called on a separate thread,
+ // but finishing up the process needs to be done on the main thread.
+ loop_schedule_fast(proc->loop, event_create(pty_proc_finish_when_eof, ptyproc));
}
-static void start_wait_eof_timer(void **argv)
+static void pty_proc_finish_when_eof(void **argv)
FUNC_ATTR_NONNULL_ALL
{
PtyProc *ptyproc = (PtyProc *)argv[0];
if (ptyproc->finish_wait != NULL) {
- uv_timer_start(&ptyproc->wait_eof_timer, wait_eof_timer_cb, 200, 200);
+ if (pty_proc_can_finish(ptyproc)) {
+ pty_proc_finish(ptyproc);
+ } else {
+ uv_timer_start(&ptyproc->wait_eof_timer, wait_eof_timer_cb, 200, 200);
+ }
}
}
+static bool pty_proc_can_finish(PtyProc *ptyproc)
+{
+ Proc *proc = (Proc *)ptyproc;
+
+ assert(ptyproc->finish_wait != NULL);
+ return proc->out.s.closed || proc->out.did_eof || !uv_is_readable(proc->out.s.uvstream);
+}
+
/// @returns zero on success, or negative error code.
int pty_proc_spawn(PtyProc *ptyproc)
FUNC_ATTR_NONNULL_ALL
@@ -120,7 +132,7 @@ int pty_proc_spawn(PtyProc *ptyproc)
ptyproc->wait_eof_timer.data = (void *)ptyproc;
if (!RegisterWaitForSingleObject(&ptyproc->finish_wait,
proc_handle,
- pty_proc_finish1,
+ pty_proc_terminate_cb,
ptyproc,
INFINITE,
WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) {
@@ -213,16 +225,13 @@ static void wait_eof_timer_cb(uv_timer_t *wait_eof_timer)
FUNC_ATTR_NONNULL_ALL
{
PtyProc *ptyproc = wait_eof_timer->data;
- Proc *proc = (Proc *)ptyproc;
-
- assert(ptyproc->finish_wait != NULL);
- if (proc->out.s.closed || proc->out.did_eof || !uv_is_readable(proc->out.s.uvstream)) {
+ if (pty_proc_can_finish(ptyproc)) {
uv_timer_stop(&ptyproc->wait_eof_timer);
- pty_proc_finish2(ptyproc);
+ pty_proc_finish(ptyproc);
}
}
-static void pty_proc_finish2(PtyProc *ptyproc)
+static void pty_proc_finish(PtyProc *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
Proc *proc = (Proc *)ptyproc;