From nobody@FreeBSD.org  Wed Feb 15 05:16:35 2012
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 54708106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 15 Feb 2012 05:16:35 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id 359858FC0C
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 15 Feb 2012 05:16:35 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id q1F5GYN8090635
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 15 Feb 2012 05:16:34 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id q1F5GY1b090633;
	Wed, 15 Feb 2012 05:16:34 GMT
	(envelope-from nobody)
Message-Id: <201202150516.q1F5GY1b090633@red.freebsd.org>
Date: Wed, 15 Feb 2012 05:16:34 GMT
From: Matthew Story <matthewstory@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [PATCH][bin] xargs incorrect pointer passed to waitchildren function
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         165164
>Category:       bin
>Synopsis:       [PATCH][bin] xargs(1) incorrect pointer passed to waitchildren function
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    jilles
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Feb 15 05:20:05 UTC 2012
>Closed-Date:    Fri Feb 24 12:42:29 UTC 2012
>Last-Modified:  Fri Feb 24 12:42:29 UTC 2012
>Originator:     Matthew Story
>Release:        9.0
>Organization:
>Environment:
FreeBSD matt9fromouterspace 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan  3 07:15:25 UTC 2012     root@obrian.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
*argv is manipulated in main to account for Jflag replacement strings (moving argv into av, and leaving *argv a pointer to the first argument following a Jflag replacement string argument || NULL if Jflag not set):

    if (*argv == NULL)
        cnt = strlen(*bxp++ = echo);
    else {
        do {
            if (Jflag && strcmp(*argv, replstr) == 0) {
                char **avj;
                jfound = 1;
                argv++;
                for (avj = argv; *avj; avj++)
                    cnt += strlen(*avj) + 1;
                break;
            }   
            cnt += strlen(*bxp++ = *argv) + 1;
        } while (*++argv != NULL);
    } 

*argv is then passed to parse_input, which passes *av to prerun, which in turn passes *av (locally argv) to waitchildren for diagnostic purposes, while the calls from parse_input itself pass *argv to waitchildren for diagnostic purposes.  This incongruity means that calls directly from parse_input (only in cases after EOF has been seen) take either NULL or the first argument after a Jflag string argument as utility name for diagnostic purposes, leading to output like:

xargs: (null): No such file or directory
>How-To-Repeat:
Found this issue after applying patch from PR 165155, which provides POSIX-compliant diagnostic information on exit 255 and children terminated by signals.  Condition exists, but is masked for the most part by a race on line 568 (WNOHANG wait immediately following vfork, execvp), if you comment out that line:

/* waitchildren(*argv, 0); */

You will reliably see the following behavior:

$ # this will work unless you have a this_does_not_exist in your PATH
$ echo "hi" | ./xargs -P10 -n1 this_does_not_exist
xargs: (null): No such file or directory
$ # this should read: xargs: hi: No such file or directory
$ echo "this_does_not_exist" | ./xargs -J % % sh
xargs: sh: No such file or directory

You can alternalively apply the patch from PR 165155, and the following will always yield the (null) error condition:

$ jot - 1 10 | ./xargs -P10 -n12 sh -c 'sleep 1; exit 255'
xargs: (null): exited with status 255, aborting

This issue should be resolved prior to patching PR 165155, I will make a note in that ticket as well.  Following applying the patch:

$ echo "hi" | ./xargs blah
xargs: blah: No such file or directory
$ echo "hi" | ./xargs -J % % sh   
xargs: hi: No such file or directory

And for the PR 165155 case:

$ jot - 1 10 | ./xargs -P10 -n12 sh -c 'sleep 1; exit 255'
xargs: sh: exited with status 255, aborting
>Fix:
Apply patch.  This program looks like it needs a larger re-factor, but the solution provided in the patch is to send *av to waitchildren instead of *argv (which is a pointer to the first argument following a Jflag replacement string || null) to make the behavior congruent with the argument list passed to prerun (locally argv).

Patch attached with submission follows:

--- a/usr.bin/xargs/xargs.c	2012-02-14 22:54:29.000000000 -0500
+++ b/usr.bin/xargs/xargs.c	2012-02-14 16:46:37.000000000 -0500
@@ -281,7 +281,7 @@
 	case EOF:
 		/* No arguments since last exec. */
 		if (p == bbp) {
-			waitchildren(*argv, 1);
+			waitchildren(*av, 1);
 			exit(rval);
 		}
 		goto arg1;
@@ -368,7 +368,7 @@
 			}
 			prerun(argc, av);
 			if (ch == EOF || foundeof) {
-				waitchildren(*argv, 1);
+				waitchildren(*av, 1);
 				exit(rval);
 			}
 			p = bbp;


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->jilles 
Responsible-Changed-By: jilles 
Responsible-Changed-When: Mon Feb 20 20:47:47 UTC 2012 
Responsible-Changed-Why:  
Take. 

This looks useful for standards/165155. I think the "race" between 
vfork/_exit/waitpid(WNOHANG) will always work as expected, however, 
because of the semantics of vfork and how the FreeBSD kernel signals 
_exit->vfork and _exit->waitpid at the same time during exit1. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=165164 
State-Changed-From-To: open->closed 
State-Changed-By: jilles 
State-Changed-When: Fri Feb 24 12:41:41 UTC 2012 
State-Changed-Why:  
Committed as part of the fix for standards/165155 in r232108. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=165164 
>Unformatted:
