Change to xargs to avoid orphaning of utility processes on
signal|exit 255 from child
Matthew Story
matthewstory at gmail.com
Fri Feb 17 00:40:29 UTC 2012
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
More information about the freebsd-arch
mailing list