All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jilles Tjoelker <jilles@stack.nl>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Sjon Hortensius <Sjon@hortensius.net>, dash@vger.kernel.org
Subject: Re: Fwd: bug? Spawned childs always remain in zombie state
Date: Fri, 23 Aug 2013 14:20:20 +0200	[thread overview]
Message-ID: <20130823122020.GA31555@stack.nl> (raw)
In-Reply-To: <20130823104444.GE10632@gondor.apana.org.au>

On Fri, Aug 23, 2013 at 08:44:44PM +1000, Herbert Xu wrote:
> On Sun, Jan 20, 2013 at 12:04:04PM +0000, Sjon Hortensius wrote:
> > Hi. I'm trying to create a script which monitors a directory using
> > inotify and spawns a background process for all events. However I
> > found that all childs will remain in zombie state until the script
> > quits and I am unable to find a proper fix.

> > A minimal testcase:

> > #!/bin/dash
> > while true
> > do
> >     sleep 1 &
> > #    jobs >/dev/null
> > done

> > If you open a second terminal you'll see that all the 'sleep'
> > processes end up being defunct. I have tried playing with `set -ma`
> > but the only workaround I found is the commented 'jobs' line.
> > Uncommenting that line will result in expected behavior where childs
> > are properly reaped. Is this a bug, or is there an alternative
> > solution I'm missing?

> You need to wait on them as otherwise dash has to keep them around
> in case you call wait(1) later on.

The shell need not remember the processes indefinitely. Per POSIX (XCU
2.9.3.1 Asynchronous Lists), the application must reference $! before
starting another asynchronous list if it wants to use the wait builtin
for that particular process later on. (Note that this means that jobs -p
is not good enough even when the job consists of a single process, and
that printing $! can add memory leaks to a script.)

POSIX also restricts an operandless wait builtin to "known process IDs".
This seems inappropriate: there are many scripts that start multiple
asynchronous lists without referencing $! and expect operandless wait to
wait for all of them. Therefore, all jobs must be remembered while they
are running. However, if $! was not referenced for them and they are not
the most recent asynchronous list, they can be discarded when they
terminate. I implemented this in FreeBSD sh and it appears to work well.

An additional issue occurs when multiple asynchronous lists are started
without a foreground process, here-document that requires a fork,
operandless jobs builtin or wait builtin in between. In that case, dash
never calls wait3() and zombies accumulate. Although the example could
be considered a fork bomb and relies on the child processes getting CPU
time often enough, this may legitimately happen if the loop contains a
read builtin. In FreeBSD sh, I added a check for zombies before forking
the first process of a background job. Some other shells call waitpid()
or similar from a SIGCHLD handler; this reaps zombies faster at the cost
of more complex code (signal handler performing non-trivial work).

-- 
Jilles Tjoelker

      reply	other threads:[~2013-08-23 12:20 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CAMqPLXWsMhPBjYa3JnCmuO=M6m2F=hSdiEfRx390VKdgC5qxZg@mail.gmail.com>
2013-01-20 12:04 ` Fwd: bug? Spawned childs always remain in zombie state Sjon Hortensius
2013-08-23 10:44   ` Herbert Xu
2013-08-23 12:20     ` Jilles Tjoelker [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130823122020.GA31555@stack.nl \
    --to=jilles@stack.nl \
    --cc=Sjon@hortensius.net \
    --cc=dash@vger.kernel.org \
    --cc=herbert@gondor.apana.org.au \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.