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.

PR:		bin/55346
This commit is contained in:
Jilles Tjoelker 2010-05-24 10:35:57 +00:00
parent 41fd9c6369
commit 1f65c541e8

View File

@ -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, int mode)
TRACE(("forkshell(%%%d, %p, %d) called\n", jp - jobtab, (void *)n,
mode));
INTOFF;
if (mode == FORK_BG)
checkzombies();
flushall();
pid = fork();
if (pid == -1) {
@ -1056,6 +1059,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.