]> granicus.if.org Git - vim/commitdiff
patch 8.0.1552: may leak file descriptors when executing job v8.0.1552
authorBram Moolenaar <Bram@vim.org>
Tue, 27 Feb 2018 18:10:00 +0000 (19:10 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 27 Feb 2018 18:10:00 +0000 (19:10 +0100)
Problem:    May leak file descriptors when executing job.
Solution:   Close more file descriptors. (Ozaki Kiichi, closes #2531)

src/os_unix.c
src/testdir/test_channel.vim
src/version.c

index 59fe77ace036425f8fae7b6286699f7ef4d49676..ac89955f252f71b096c3ad0dc0d7b53aa96a0aab 100644 (file)
@@ -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)
     {
index 1859afc5b8a321d430983924bc8452eae69fe110..9de3ca01f9a1a88862f48699998c2abb1d22d167 100644 (file)
@@ -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!
index 389bbb1a53297bf4c628340a29e808b632a5458c..48da8a3514534e50d979c606ee3822691c0eb1d3 100644 (file)
@@ -778,6 +778,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1552,
 /**/
     1551,
 /**/