summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-02-27 19:10:00 +0100
committerBram Moolenaar <Bram@vim.org>2018-02-27 19:10:00 +0100
commit8195247054a659fe5cbc238197634d5e13e8e8e9 (patch)
treee1069ff3af65d73c58c694eaf552ff1e27cbbeef
parent988615f26f262d9ef6472c53b48868968a6b6d16 (diff)
patch 8.0.1552: may leak file descriptors when executing jobv8.0.1552
Problem: May leak file descriptors when executing job. Solution: Close more file descriptors. (Ozaki Kiichi, closes #2531)
-rw-r--r--src/os_unix.c18
-rw-r--r--src/testdir/test_channel.vim18
-rw-r--r--src/version.c2
3 files changed, 35 insertions, 3 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index 59fe77ace0..ac89955f25 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -4601,6 +4601,12 @@ mch_call_shell(
reset_signals(); /* handle signals normally */
UNBLOCK_SIGNALS(&curset);
+# ifdef FEAT_JOB_CHANNEL
+ if (ch_log_active())
+ /* close the log file in the child */
+ ch_logfile((char_u *)"", (char_u *)"");
+# endif
+
if (!show_shell_mess || (options & SHELL_EXPAND))
{
int fd;
@@ -5454,6 +5460,12 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
reset_signals(); /* handle signals normally */
UNBLOCK_SIGNALS(&curset);
+# ifdef FEAT_JOB_CHANNEL
+ if (ch_log_active())
+ /* close the log file in the child */
+ ch_logfile((char_u *)"", (char_u *)"");
+# endif
+
# ifdef HAVE_SETSID
/* Create our own process group, so that the child and all its
* children can be kill()ed. Don't do this when using pipes,
@@ -5587,11 +5599,11 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
if (pty_master_fd >= 0)
close(pty_slave_fd); /* not used in the parent */
/* close child stdin, stdout and stderr */
- if (!use_file_for_in && fd_in[0] >= 0)
+ if (fd_in[0] >= 0)
close(fd_in[0]);
- if (!use_file_for_out && fd_out[1] >= 0)
+ if (fd_out[1] >= 0)
close(fd_out[1]);
- if (!use_out_for_err && !use_file_for_err && fd_err[1] >= 0)
+ if (fd_err[1] >= 0)
close(fd_err[1]);
if (channel != NULL)
{
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index 1859afc5b8..9de3ca01f9 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -23,6 +23,21 @@ func s:run_server(testfunc, ...)
call RunServer('test_channel.py', a:testfunc, a:000)
endfunc
+" Return a list of open files.
+" Can be used to make sure no resources leaked.
+" Returns an empty list on systems where this is not supported.
+func s:get_resources()
+ let pid = getpid()
+
+ if has('mac')
+ return systemlist('lsof -p ' . pid . ' | awk ''$4~/^[0-9]*[rwu]$/&&$5=="REG"{print$NF}''')
+ elseif isdirectory('/proc/' . pid . '/fd/')
+ return systemlist('readlink /proc/' . pid . '/fd/* | grep -v ''^/dev/''')
+ else
+ return []
+ endif
+endfunc
+
let g:Ch_responseMsg = ''
func Ch_requestHandler(handle, msg)
let g:Ch_responseHandle = a:handle
@@ -620,6 +635,7 @@ func Test_nl_write_out_file()
call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput'))
finally
call Stop_g_job()
+ call assert_equal(-1, match(s:get_resources(), '\(^\|/\)Xoutput$'))
call delete('Xoutput')
endtry
endfunc
@@ -663,6 +679,7 @@ func Test_nl_write_both_file()
call assert_equal(['line one', 'line two', 'this', 'AND this', 'that', 'AND that'], readfile('Xoutput'))
finally
call Stop_g_job()
+ call assert_equal(-1, match(s:get_resources(), '\(^\|/\)Xoutput$'))
call delete('Xoutput')
endtry
endfunc
@@ -1662,6 +1679,7 @@ func Test_raw_passes_nul()
call assert_equal("asdf\nasdf", getline(1))
call assert_equal("xxx\n", getline(2))
call assert_equal("\nyyy", getline(3))
+ call assert_equal(-1, match(s:get_resources(), '\(^\|/\)Xtestwrite$'))
call delete('Xtestwrite')
bwipe!
diff --git a/src/version.c b/src/version.c
index 389bbb1a53..48da8a3514 100644
--- a/src/version.c
+++ b/src/version.c
@@ -779,6 +779,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1552,
+/**/
1551,
/**/
1550,