mirror of
https://github.com/neovim/neovim.git
synced 2026-03-31 04:42:03 +00:00
fix(process): don't limit PTY master remaining data size
This commit is contained in:
@@ -368,20 +368,27 @@ static void flush_stream(Proc *proc, RStream *stream)
|
||||
return;
|
||||
}
|
||||
|
||||
// Maximal remaining data size of terminated process is system
|
||||
// buffer size.
|
||||
// Also helps with a child process that keeps the output streams open. If it
|
||||
// keeps sending data, we only accept as much data as the system buffer size.
|
||||
// Otherwise this would block cleanup/teardown.
|
||||
int system_buffer_size = 0;
|
||||
int err = uv_recv_buffer_size((uv_handle_t *)&stream->s.uv.pipe,
|
||||
&system_buffer_size);
|
||||
if (err) {
|
||||
system_buffer_size = ARENA_BLOCK_SIZE;
|
||||
size_t max_bytes = SIZE_MAX;
|
||||
#ifdef MSWIN
|
||||
if (true) {
|
||||
#else
|
||||
// Don't limit remaining data size of PTY master unless when tearing down, as it may
|
||||
// have more remaining data than system buffer size (at least on Linux). #3030
|
||||
if (proc->type != kProcTypePty || proc_is_tearing_down) {
|
||||
#endif
|
||||
// Maximal remaining data size of terminated process is system buffer size.
|
||||
// Also helps with a child process that keeps the output streams open. If it
|
||||
// keeps sending data, we only accept as much data as the system buffer size.
|
||||
// Otherwise this would block cleanup/teardown.
|
||||
int system_buffer_size = 0;
|
||||
// All members of the stream->s.uv union share the same address.
|
||||
int err = uv_recv_buffer_size((uv_handle_t *)&stream->s.uv, &system_buffer_size);
|
||||
if (err != 0) {
|
||||
system_buffer_size = ARENA_BLOCK_SIZE;
|
||||
}
|
||||
max_bytes = stream->num_bytes + (size_t)system_buffer_size;
|
||||
}
|
||||
|
||||
size_t max_bytes = stream->num_bytes + (size_t)system_buffer_size;
|
||||
|
||||
// Read remaining data.
|
||||
while (!stream->s.closed && stream->num_bytes < max_bytes) {
|
||||
// Remember number of bytes before polling
|
||||
|
||||
@@ -32,12 +32,14 @@ static void help(void)
|
||||
puts(" shell-test -t {prompt text} EXE \"prog args...\"");
|
||||
puts(" Prints \"{prompt text} $ progs args...\" to stderr.");
|
||||
puts(" shell-test REP N {text}");
|
||||
puts(" Prints \"{lnr}: {text}\\n\" to stdout N times, taking N milliseconds.");
|
||||
puts(" Prints \"{lnr}: {text}\\n\" to stdout N times, pausing every 100 lines.");
|
||||
puts(" Example:");
|
||||
puts(" shell-test REP 97 \"foo bar\"");
|
||||
puts(" 0: foo bar");
|
||||
puts(" ...");
|
||||
puts(" 96: foo bar");
|
||||
puts(" shell-test REPFAST N {text}");
|
||||
puts(" Like REP, but print as fast as possible and then exit immediately.");
|
||||
puts(" shell-test INTERACT");
|
||||
puts(" Prints \"interact $ \" to stderr, and waits for \"exit\" input.");
|
||||
puts(" shell-test EXIT {code}");
|
||||
@@ -71,9 +73,10 @@ int main(int argc, char **argv)
|
||||
} else {
|
||||
fprintf(stderr, "ready $ ");
|
||||
}
|
||||
} else if (strcmp(argv[1], "REP") == 0) {
|
||||
} else if (strcmp(argv[1], "REP") == 0 || strcmp(argv[1], "REPFAST") == 0) {
|
||||
bool fast = strcmp(argv[1], "REPFAST") == 0;
|
||||
if (argc != 4) {
|
||||
fprintf(stderr, "REP expects exactly 3 arguments\n");
|
||||
fprintf(stderr, "REP/REPFAST expects exactly 3 arguments\n");
|
||||
return 4;
|
||||
}
|
||||
int count = 0;
|
||||
@@ -83,7 +86,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
for (int i = 0; i < count; i++) {
|
||||
printf("%d: %s\n", i, argv[3]);
|
||||
if (i % 100 == 0) {
|
||||
if (!fast && i % 100 == 0) {
|
||||
usleep(1000); // Wait 1 ms (simulate typical output).
|
||||
}
|
||||
fflush(NULL);
|
||||
|
||||
@@ -758,6 +758,25 @@ describe(':terminal buffer', function()
|
||||
]])
|
||||
end)
|
||||
|
||||
it('does not drop data when job exits immediately after output #3030', function()
|
||||
local screen = Screen.new(50, 7)
|
||||
api.nvim_create_autocmd('TermClose', { command = 'let g:did_termclose = 1' })
|
||||
fn.jobstart({ testprg('shell-test'), 'REPFAST', '20000', 'TEST' }, { term = true })
|
||||
retry(nil, nil, function()
|
||||
eq(1, api.nvim_get_var('did_termclose'))
|
||||
end)
|
||||
feed('i')
|
||||
screen:expect([[
|
||||
19996: TEST |
|
||||
19997: TEST |
|
||||
19998: TEST |
|
||||
19999: TEST |
|
||||
|
|
||||
[Process exited 0]^ |
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('handles unprintable chars', function()
|
||||
local screen = Screen.new(50, 7)
|
||||
feed 'i'
|
||||
|
||||
Reference in New Issue
Block a user