shell: Use job_write_cb for closing stdin

Commit @45525853d352 removed usage of the `job_write_cb` for closing stdin due
to a memory error, but that doesn't work anymore because `job_close_in` closes
stdin immediately, possibly trimming input data before it is fully written.

Since most memory issues with jobs have been fixed, re-add the `job_write_cb`
call to ensure stdin is only closed when it should. Also add tests for scenarios
where using the callback makes a difference.
This commit is contained in:
Thiago de Arruda 2014-11-10 09:19:27 -03:00
parent ab826d88f6
commit 3e8ef31ada
2 changed files with 37 additions and 2 deletions

View File

@ -244,6 +244,9 @@ static int shell(const char *cmd,
job_stop(job); job_stop(job);
return -1; return -1;
} }
// close the input stream after everything is written
job_write_cb(job, shell_write_cb);
} else {
// close the input stream, let the process know that no more input is // close the input stream, let the process know that no more input is
// coming // coming
job_close_in(job); job_close_in(job);
@ -447,3 +450,9 @@ static void write_output(char *output, size_t remaining)
curbuf->b_no_eol_lnum = 0; curbuf->b_no_eol_lnum = 0;
} }
} }
static void shell_write_cb(WStream *wstream, void *data, int status)
{
Job *job = data;
job_close_in(job);
}

View File

@ -3,8 +3,8 @@
-- - `systemlist()` -- - `systemlist()`
local helpers = require('test.functional.helpers') local helpers = require('test.functional.helpers')
local eq, clear, eval, feed = local eq, clear, eval, feed, nvim =
helpers.eq, helpers.clear, helpers.eval, helpers.feed helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.nvim
local function create_file_with_nuls(name) local function create_file_with_nuls(name)
@ -55,6 +55,21 @@ describe('system()', function()
end) end)
end) end)
describe('passing a lot of input', function()
it('returns the program output', function()
local input = {}
-- write more than 1mb of data, which should be enough to overcome
-- the os buffer limit and force multiple event loop iterations to write
-- everything
for i = 1, 0xffff do
input[#input + 1] = '01234567890ABCDEFabcdef'
end
input = table.concat(input, '\n')
nvim('set_var', 'input', input)
eq(input, eval('system("cat -", g:input)'))
end)
end)
describe('passing number as input', function() describe('passing number as input', function()
it('stringifies the input', function() it('stringifies the input', function()
eq('1', eval('system("cat", 1)')) eq('1', eval('system("cat", 1)'))
@ -129,6 +144,17 @@ describe('systemlist()', function()
end) end)
end) end)
describe('passing a lot of input', function()
it('returns the program output', function()
local input = {}
for i = 1, 0xffff do
input[#input + 1] = '01234567890ABCDEFabcdef'
end
nvim('set_var', 'input', input)
eq(input, eval('systemlist("cat -", g:input)'))
end)
end)
describe('with output containing NULs', function() describe('with output containing NULs', function()
local fname = 'Xtest' local fname = 'Xtest'