| 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 |
| |
| |
| |
| |
| |
| *** 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 |
| |
| |
| |
| *** 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 /// |