process: Remove indeterminism that causes reordering of pty events

Since pty events are queued, it is possible that the reads will be reordered.
Example scenario:

In the terminal you have output combined from stdout and stderr. A program
generates output, first you have some output on stdout, then output on stderr,
output on stdout, output on stderr,...  The whole output should be interleaved
from both streams.

Each output generates a read_event and they are placed in the same queue. If the
queue is processed, the first read_event will send the whole stdout output to
the terminal (on_job_output() consumes the whole buffer). The next read_event is
similar for stderr. The remaining read events do nothing because now both
RBuffer are already empty. So the terminal would show first the stdout output
and after that the stderr output.

This commit fixes the problem by disabling stderr stream in pty processes.
That's ok because they all represent the same stream(duplicate file
descriptors), plus one stream is simpler to deal with.
This commit is contained in:
oni-link 2015-08-07 23:26:01 -03:00 committed by Thiago de Arruda
parent 502aee690c
commit 166d8c799f
2 changed files with 4 additions and 4 deletions

View File

@ -21051,7 +21051,9 @@ static inline TerminalJobData *common_job_init(char **argv, ufunc_T *on_stdout,
proc->argv = argv;
proc->in = &data->in;
proc->out = &data->out;
proc->err = &data->err;
if (!pty) {
proc->err = &data->err;
}
proc->cb = on_process_exit;
proc->events = data->events;
return data;

View File

@ -37,6 +37,7 @@ bool pty_process_spawn(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
Process *proc = (Process *)ptyproc;
assert(!proc->err);
uv_signal_start(&proc->loop->children_watcher, chld_handler, SIGCHLD);
ptyproc->winsize = (struct winsize){ptyproc->height, ptyproc->width, 0, 0};
struct termios termios;
@ -70,9 +71,6 @@ bool pty_process_spawn(PtyProcess *ptyproc)
if (proc->out && !set_duplicating_descriptor(master, &proc->out->uv.pipe)) {
goto error;
}
if (proc->err && !set_duplicating_descriptor(master, &proc->err->uv.pipe)) {
goto error;
}
ptyproc->tty_fd = master;
proc->pid = pid;