xargs: wait for process before prompting in interactive mode (-p)

In interactive mode, there is a race between xargs prompting
about the next command to be run, vs. the execution of the
echo command:

  $ echo 1 2 | xargs -n 1 -p
  /bin/echo 1 ?...y
  /bin/echo 2 ?...1
  y
  2

This behavior violates POSIX:
(http://pubs.opengroup.org/onlinepubs/9699919799/utilities/xargs.html):

  The xargs utility shall then invoke the constructed command line
  and wait for its completion. This sequence shall be repeated until
  one of the following occurs: [...]

* xargs/xargs.c (xargs_do_exec): Move the code for waiting for forked
processes up, so that the child process terminates before we prompt
for the next command.
* NEWS: Mention the fix.

Reported by jidanni@jidanni.org in
http://lists.gnu.org/archive/html/bug-findutils/2013-07/msg00015.html
This commit is contained in:
2013-08-02 14:17:14 +02:00
committed by James Youngman
parent 29f3173a56
commit 169161fa0e
3 changed files with 18 additions and 7 deletions

View File

@@ -1,3 +1,11 @@
2013-09-21 Bernhard Voelker <mail@bernhard-voelker.de>
xargs: wait for process before prompting in interactive mode (-p)
* xargs/xargs.c (xargs_do_exec): Move the code for waiting for
forked processes up, so that the child process terminates before
we prompt for the next command.
* NEWS: Mention the fix.
2013-09-21 Dmitry V. Levin <ldv@altlinux.org>
find: fix potential buffer overflow in -execdir and -okdir.

2
NEWS
View File

@@ -36,6 +36,8 @@ database, though they are in the ChangeLog:
*** Don't delete header files in "lib/" for "make clean".
*** xargs: wait for process before prompting in interactive mode (-p)
These following fixed bugs are recorded at
https://savannah.gnu.org/bugs/?group=findutils:

View File

@@ -1179,15 +1179,16 @@ xargs_do_exec (struct buildcmd_control *ctl, void *usercontext, int argc, char *
(void) argc;
(void) usercontext;
if (proc_max)
{
while (procs_executing >= proc_max)
{
wait_for_proc (false, 1u);
}
}
if (!query_before_executing || print_args (true))
{
if (proc_max)
{
while (procs_executing >= proc_max)
{
wait_for_proc (false, 1u);
}
}
if (!query_before_executing && print_command)
print_args (false);