Blob Blame History Raw
To: vim_dev@googlegroups.com
Subject: Patch 7.3.296
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
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    ///