To: vim_dev@googlegroups.com Subject: Patch 7.3.296 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.3.296 Problem: When writing to an external command a zombie process may be left behind. Solution: Wait on the process. (James Vega) Files: src/os_unix.c *** ../vim-7.3.295/src/os_unix.c 2011-09-07 14:06:38.000000000 +0200 --- src/os_unix.c 2011-09-07 14:54:11.000000000 +0200 *************** *** 154,159 **** --- 154,166 ---- static void may_core_dump __ARGS((void)); + #ifdef HAVE_UNION_WAIT + typedef union wait waitstatus; + #else + typedef int waitstatus; + #endif + static int wait4pid __ARGS((pid_t, waitstatus *)); + static int WaitForChar __ARGS((long)); #if defined(__BEOS__) int RealWaitForChar __ARGS((int, long, int *)); *************** *** 3660,3665 **** --- 3667,3713 ---- /* Nothing to do. */ } + /* + * Wait for process "child" to end. + * Return "child" if it exited properly, <= 0 on error. + */ + static pid_t + wait4pid(child, status) + pid_t child; + waitstatus *status; + { + pid_t wait_pid = 0; + + while (wait_pid != child) + { + # ifdef _THREAD_SAFE + /* Ugly hack: when compiled with Python threads are probably + * used, in which case wait() sometimes hangs for no obvious + * reason. Use waitpid() instead and loop (like the GUI). */ + # ifdef __NeXT__ + wait_pid = wait4(child, status, WNOHANG, (struct rusage *)0); + # else + wait_pid = waitpid(child, status, WNOHANG); + # endif + if (wait_pid == 0) + { + /* Wait for 1/100 sec before trying again. */ + mch_delay(10L, TRUE); + continue; + } + # else + wait_pid = wait(status); + # endif + if (wait_pid <= 0 + # ifdef ECHILD + && errno == ECHILD + # endif + ) + break; + } + return wait_pid; + } + int mch_call_shell(cmd, options) char_u *cmd; *************** *** 4234,4240 **** { MSG_PUTS(_("\nCannot fork\n")); } ! else if (wpid == 0) { linenr_T lnum = curbuf->b_op_start.lnum; int written = 0; --- 4282,4288 ---- { MSG_PUTS(_("\nCannot fork\n")); } ! else if (wpid == 0) /* child */ { linenr_T lnum = curbuf->b_op_start.lnum; int written = 0; *************** *** 4242,4248 **** char_u *s; size_t l; - /* child */ close(fromshell_fd); for (;;) { --- 4290,4295 ---- *************** *** 4287,4293 **** } _exit(0); } ! else { close(toshell_fd); toshell_fd = -1; --- 4334,4340 ---- } _exit(0); } ! else /* parent */ { close(toshell_fd); toshell_fd = -1; *************** *** 4584,4590 **** * typed characters (otherwise we would lose typeahead). */ # ifdef __NeXT__ ! wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0); # else wait_pid = waitpid(pid, &status, WNOHANG); # endif --- 4631,4637 ---- * typed characters (otherwise we would lose typeahead). */ # ifdef __NeXT__ ! wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0); # else wait_pid = waitpid(pid, &status, WNOHANG); # endif *************** *** 4633,4665 **** * Don't wait if wait_pid was already set above, indicating the * child already exited. */ ! while (wait_pid != pid) ! { ! # ifdef _THREAD_SAFE ! /* Ugly hack: when compiled with Python threads are probably ! * used, in which case wait() sometimes hangs for no obvious ! * reason. Use waitpid() instead and loop (like the GUI). */ ! # ifdef __NeXT__ ! wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0); ! # else ! wait_pid = waitpid(pid, &status, WNOHANG); ! # endif ! if (wait_pid == 0) ! { ! /* Wait for 1/100 sec before trying again. */ ! mch_delay(10L, TRUE); ! continue; ! } ! # else ! wait_pid = wait(&status); ! # endif ! if (wait_pid <= 0 ! # ifdef ECHILD ! && errno == ECHILD ! # endif ! ) ! break; ! } # ifdef FEAT_GUI /* Close slave side of pty. Only do this after the child has --- 4680,4687 ---- * Don't wait if wait_pid was already set above, indicating the * child already exited. */ ! if (wait_pid != pid) ! wait_pid = wait4pid(pid, &status); # ifdef FEAT_GUI /* Close slave side of pty. Only do this after the child has *************** *** 4672,4678 **** --- 4694,4703 ---- /* Make sure the child that writes to the external program is * dead. */ if (wpid > 0) + { kill(wpid, SIGKILL); + wait4pid(wpid, NULL); + } /* * Set to raw mode right now, otherwise a CTRL-C after *** ../vim-7.3.295/src/version.c 2011-09-07 14:06:39.000000000 +0200 --- src/version.c 2011-09-07 15:03:24.000000000 +0200 *************** *** 711,712 **** --- 711,714 ---- { /* Add new patch number below this line */ + /**/ + 296, /**/ -- If your company is not involved in something called "ISO 9000" you probably have no idea what it is. If your company _is_ involved in ISO 9000 then you definitely have no idea what it is. (Scott Adams - The Dilbert principle) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///