Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 May 2011 22:28:07 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r222208 - stable/8/bin/sh
Message-ID:  <201105222228.p4MMS7LK093514@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Sun May 22 22:28:07 2011
New Revision: 222208
URL: http://svn.freebsd.org/changeset/base/222208

Log:
  MFC r208489,r216208: sh: Reap any zombies before forking for a background
  command.
  
  This prevents accumulating huge amounts of zombies if a script executes
  many background commands but no external commands or subshells.
  
  Note that zombies will not be reaped during long calculations (within
  the shell process) or read builtins, but those actions do not create
  more zombies.
  
  The terminated background commands will also still be remembered by the
  shell.
  
  r216208 fixes a bug in r208489 that could cause a multi-command pipeline to
  be marked as done before all processes had been created.
  
  PR:		bin/55346

Modified:
  stable/8/bin/sh/jobs.c
Directory Properties:
  stable/8/bin/sh/   (props changed)

Modified: stable/8/bin/sh/jobs.c
==============================================================================
--- stable/8/bin/sh/jobs.c	Sun May 22 22:17:06 2011	(r222207)
+++ stable/8/bin/sh/jobs.c	Sun May 22 22:28:07 2011	(r222208)
@@ -91,6 +91,7 @@ static void freejob(struct job *);
 static struct job *getjob(char *);
 static pid_t dowait(int, struct job *);
 static pid_t waitproc(int, int *);
+static void checkzombies(void);
 static void cmdtxt(union node *);
 static void cmdputs(const char *);
 #if JOBS
@@ -400,7 +401,7 @@ showjobs(int change, int mode)
 	struct job *jp;
 
 	TRACE(("showjobs(%d) called\n", change));
-	while (dowait(0, (struct job *)NULL) > 0);
+	checkzombies();
 	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
 		if (! jp->used)
 			continue;
@@ -742,6 +743,8 @@ forkshell(struct job *jp, union node *n,
 	TRACE(("forkshell(%%%td, %p, %d) called\n", jp - jobtab, (void *)n,
 	    mode));
 	INTOFF;
+	if (mode == FORK_BG && (jp == NULL || jp->nprocs == 0))
+		checkzombies();
 	flushall();
 	pid = fork();
 	if (pid == -1) {
@@ -948,7 +951,7 @@ dowait(int block, struct job *job)
 	INTOFF;
 	thisjob = NULL;
 	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
-		if (jp->used) {
+		if (jp->used && jp->nprocs > 0) {
 			done = 1;
 			stopped = 1;
 			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
@@ -1062,6 +1065,15 @@ stoppedjobs(void)
 	return (0);
 }
 
+
+static void
+checkzombies(void)
+{
+	while (njobs > 0 && dowait(0, NULL) > 0)
+		;
+}
+
+
 /*
  * Return a string identifying a command (to be printed by the
  * jobs command.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105222228.p4MMS7LK093514>