Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Feb 2012 19:09:26 -0500
From:      Matthew Story <matthewstory@gmail.com>
To:        freebsd-arch@freebsd.org
Subject:   Change to xargs to avoid orphaning of utility processes on signal|exit 255 from child
Message-ID:  <CAB%2B9ogetrht1Ttf53vSbq7L5Fe9DbB5igSynKM3=tjZh0z0_ew@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
Apologies if this is the wrong list, I would like to submit a patch that
changes the behavior of xargs(1) on signal to child utility process or
child utility process exiting 255.  The patch(es) is|are available here:

    http://axe0.blackskyresearch.net/patches/matt/xargs.no_orphan.patch.txt--
this version will apply to current xargs, and adds diagnostic
information for exit 255|signal to utility, as required by POSIX (see
PR165155).

http://axe0.blackskyresearch.net/patches/matt/xargs.no_orphan.PR165155.patch.txt--
this version will apply on top of the patch in PR165155, as the errx
calls in that patch need to be modified to warnx calls.

I will happily provide a third option without diagnostics if that is useful
independent of PR165155.  Currently, if a child exits 255, or is terminated
via signal, the xargs process exits immediately with exit status 1, with
maxprocs > 1, this orphans all outstanding child processes:

$ jot - 1 10 | time xargs -P2 -n1 sh -c 'echo "$1: $$"; sleep $1; [ $1 -eq
1 ] && kill $$; echo "$1: $$:done";' worker
1: 69752
2: 69753
        1.00 real         0.00 user         0.00 sys
$ 2: 69753:done
$ # or ...
$ jot - 1 10 | time xargs -P2 -n1 sh -c 'echo "$1: $$"; sleep $1; [ $1 -eq
1 ] && exit 255; echo "$1: $$:done";' worker
1: 70379
2: 70380
        1.00 real         0.00 user         0.00 sys
$ 2: 70380:done

This behavior is expected per xargs(1):

     The xargs utility exits immediately (without processing any further
     input) if a command line cannot be assembled, utility cannot be
invoked,
     an invocation of utility is terminated by a signal, or an invocation of
     utility exits with a value of 255.

Per the POSIX specification, xargs is only required to stop processing
input, and to exit 1-125, it is not exit immediately (utility here is the
utility invoked by xargs, not xargs itself):

If a command line meeting the specified requirements cannot be assembled,
the utility cannot be invoked, an invocation of the utility is terminated
by a signal, or an invocation of the utility exits with exit status 255,
the *xargs* utility shall write a diagnostic message and exit without
processing any remaining input.

The patch preserves orphaning when the xargs process itself is terminated
by signal, but augments the behavior when a child utility process is
terminated by signal or exits 255 to wait for other existing child
utilities until exiting 1.  My reasoning for this (beyond orphaning
nastiness) is that I always want to fail as soon as I know an operation is
fatal, and then clean-up.  By orphaning children, there is no reliable way
to clean-up following use of the 255 exit code (or signal termination):

$ # a contrived example forcing a race-condition, with a clean-up function.
$ mkdir -p foo; jot - 1 10 | xargs -P5 -n1 sh -c 'sleep $1; touch foo/$1;
exit 255;' worker || find foo -type f -delete
$ # demonstration that cleanup is not possible
$ sleep 5 && ls -l foo
total 2
-rw-r--r--  1 matt  matt  0 Feb 16 19:01 2
-rw-r--r--  1 matt  matt  0 Feb 16 19:01 3
-rw-r--r--  1 matt  matt  0 Feb 16 19:01 4
-rw-r--r--  1 matt  matt  0 Feb 16 19:01 5

Following the patch, we get a nice and reliable cleanup, as we have no
orphans:
$ mkdir -p foo; jot - 1 10 | usr.bin/xargs/xargs -P5 -n1 sh -c 'sleep $1;
touch foo/$1; exit 255;' worker || find foo -type f -delete
xargs: sh: exited with status 255, aborting
xargs: sh: exited with status 255, aborting
xargs: sh: exited with status 255, aborting
xargs: sh: exited with status 255, aborting
xargs: sh: exited with status 255, aborting
$ ls -l foo/
total 0

Please let me know what you think, I would very much like to see this patch
make it's way into xargs as I find this short-circuit behavior nearly very
usable, and it's only failing is that it orphans children unnecessarily,
resulting in unpredictable behavior.

-- 
regards,
matt



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAB%2B9ogetrht1Ttf53vSbq7L5Fe9DbB5igSynKM3=tjZh0z0_ew>