I'm finally caught up with the ast-* posts from the last 3 weeks
the posix_spawn thread inspired a new iffe C code test feature
that allows the tests to annotate reasons for test failure
(besides the test not compiling at all, which can be a valid test too)
        NOTE("reason text");
can be called (preferably once per failure) and "reason text" will appear
in the iffe --verbose (-v) output on stderr

the new version of iffe will be posted later on Monday

here is the annotated posix_spawn test
--
tst     lib_posix_spawn unistd.h stdlib.h spawn.h -Dfork=______fork note{ 
posix_spawn exists and it works and its worth using }end status{
        #include <sys/types.h>
        #include <sys/stat.h>
        #include <sys/wait.h>
        #include <spawn.h>
        #include <signal.h>
        #include <fcntl.h>
        #include <string.h>
        /* if it uses fork() why bother? */
        #undef fork
        pid_t fork _ARG_((void)) { NOTE("uses fork()"); return -1; }
        pid_t _fork _ARG_((void)) { NOTE("uses _fork()"); return -1; }
        pid_t __fork _ARG_((void)) { NOTE("uses __fork()"); return -1; }
        int
        main(argc, argv)
        int     argc;
        char**  argv;
        {
                char*                   s;
                pid_t                   pid;
                posix_spawnattr_t       attr;
                int                     n;
                int                     status;
                char*                   cmd[3];
                char                    tmp[1024];
                if (argv[1])
                        _exit(signal(SIGHUP, SIG_DFL) != SIG_IGN);
                signal(SIGHUP, SIG_IGN);
                if (posix_spawnattr_init(&attr))
                {
                        NOTE("posix_spawnattr_init() FAILED");
                        _exit(0);
                }
                if (posix_spawnattr_setpgroup(&attr, 0))
                {
                        NOTE("posix_spawnattr_setpgroup() FAILED");
                        _exit(0);
                }
                if (posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP))
                {
                        NOTE("posix_spawnattr_setflags() FAILED");
                        _exit(0);
                }
                /* first try an a.out and verify that SIGHUP is ignored */
                cmd[0] = argv[0];
                cmd[1] = "test";
                cmd[2] = 0;
                if (posix_spawn(&pid, cmd[0], 0, &attr, cmd, 0))
                {
                        NOTE("posix_spawn() FAILED");
                        _exit(0);
                }
                status = 1;
                if (wait(&status) < 0)
                {
                        NOTE("wait() FAILED");
                        _exit(0);
                }
                if (status != 0)
                {
                        NOTE("SIGHUP ignored in parent not ignored in child");
                        _exit(0);
                }
                /* must return exec-type errors or its useless to us *unless* 
there is no [v]fork() */
                n = strlen(cmd[0]);
                if (n >= (sizeof(tmp) - 3))
                {
                        NOTE("test executable path too long");
                        _exit(0);
                }
                strcpy(tmp, cmd[0]);
                tmp[n] = '.';
                tmp[n+1] = 's';
                tmp[n+2] = 'h';
                tmp[n+3] = 0;
                if ((n = open(tmp, O_CREAT|O_WRONLY, S_IRWXU|S_IRWXG|S_IRWXO)) 
< 0 ||
                    chmod(tmp, S_IRWXU|S_IRWXG|S_IRWXO) < 0 ||
                    write(n, "exit 99\n", 8) != 8 ||
                    close(n) < 0)
                {
                        NOTE("test script create FAILED");
                        _exit(0);
                }
                cmd[0] = tmp;
                n = 0; /* 0 means reject */
                pid = -1;
                if (posix_spawn(&pid, cmd[0], 0, &attr, cmd, 0))
                        n = 2; /* ENOEXEC produces posix_spawn() error => BEST 
*/
                else if (pid == -1)
                        NOTE("ENOEXEC returns pid == -1");
                else if (wait(&status) != pid)
                        NOTE("ENOEXEC produces no child process");
                else if (!WIFEXITED(status))
                        NOTE("ENOEXEC produces signal exit");
                else
                {
                        status = WEXITSTATUS(status);
                        if (status == 127)
                                n = 1; /* ENOEXEC produces exit status 127 => 
GOOD */
                        else if (status == 99)
                                NOTE("ENOEXEC invokes sh");
                        else if (status == 0)
                                NOTE("ENOEXEC reports no error");
                }
                _exit(n);
        }
}end
--
linux fails with "ENOEXEC invokes sh"
this means an executable file with invalid binary magic (errno => ENOEXEC) will
be passed to "sh" to see if it can handle it -- this tactic is wrong in a 
number of ways
        its not documented
        its not posix
        what "sh" does it call
        if its not $SHELL then can it be overridden
and finally, for ast purposes, and specifically ksh, it would foul the shell 
script
logic where if "exec() fails with ENONEXC => its a shell script", and worse, 
shell
scripts passed to posix_spawn() could be hijacked by a completely different sh 
implementation

we see these results on the ast build farm

        yes
        no                      
                no <spawn.h> and no posix_spawn() -- reasonable
        ENOEXEC invokes sh ... no
                linux
        SIGHUP ignored in parent not ignored in child ... no
                one sol10.sun4 machine -- others ok -- don't know why yet

On Thu, 5 Jul 2012 19:46:35 +0200 Irek Szczesniak wrote:
> On Wed, Jul 4, 2012 at 8:34 PM, Irek Szczesniak <[email protected]> wrote:
> > On Wed, Jul 4, 2012 at 7:32 PM, ÏÌØÇÁ ËÒÙÖÁÎÏ×ÓËÁÑ
> > <[email protected]> wrote:
> >> Michael or any other Linux guru, can you look why ksh (2012-06-28, the
> >> non doomsday release) no longer uses posix_spawn?
> >> I am getting this line when I build ksh on Fedora:
> >> iffe: test: posix_spawn exists and it works and its worth using ... no
> >>
> >> This doesn't sound right, IMO ksh should prefer (and benefit) from
> >> using posix_spawn()
> >
> > This is interesting. I thought both Linux and Solaris use
> > posix_spawn() to avoid the much more expensive vfork()/exec().

_______________________________________________
ast-developers mailing list
[email protected]
https://mailman.research.att.com/mailman/listinfo/ast-developers

Reply via email to