On 20 November 2012 16:08, Glenn Fowler <[email protected]> wrote:
>
> On Tue, 20 Nov 2012 14:09:19 +0100 Irek Szczesniak wrote:
>> On Tue, Nov 20, 2012 at 10:37 AM, Cedric Blancher
>> <[email protected]> wrote:
>> > On 1 October 2012 19:11, Glenn Fowler <[email protected]> wrote:
>> >>
>> >> On Mon, 01 Oct 2012 13:49:28 +0200 Michal Hlavinka wrote:
>> >>> > #if _lib_posix_spawn < 2
>> >>> >     if (waitpid(pid, &err, WNOHANG|WNOWAIT) == pid && EXIT_STATUS(err) 
>> >>> > == 127)
>> >>> >     {
>> >>> >             while (waitpid(pid, NiL, 0) == -1 && errno == EINTR);
>> >>> >             if (!access(path, X_OK))
>> >>> >                     errno = ENOEXEC;
>> >>> >             pid = -1;
>> >>> >     }
>> >>> > #endif
>> >>
>> >>> It will fail with EINVAL, because of WNOWAIT. This option is not
>> >>> supported in waitpid. It's supported only in waitid().
>> >>
>> >>> so you'd have to use something like
>> >>
>> >>> pid_t pid;
>> >>> siginfo_t err;
>> >>> if (!waitid(P_PID, pid, &err, WEXITED|WNOHANG|WNOWAIT) && err.si_status
>> >>> == 127)
>> >>
>> >> thanks for pointing out the WNOWAIT misuse
>> >>
>> >> alas even with the correct waitid() usage it does not solve the problem
>> >> with all posix-spawn() implementations that use exit code 127 as a catch 
>> >> all for
>> >> posix_spawn() related problems in the child process
>> >>
>> >> in the particular case of how shell implementations *portably* determine
>> >> "binary executable" vs "shell script" (exec fails with ENOEXEC)
>> >> such posix_spawn() implementations are useless
>> >>
>> >> e.g. a shell calling posix_spawn() must be able to differentiate
>> >>   EAGAIN        retry in case some resources become free
>> >>   E2BIG         diagnostic or apply xargs algorithm if appropriate
>> >>   ENOEXEC       either a shell script or a diagnostic
>> >> and you can't get that from exit status 127
>> >
>> > So GNU/Linux glibc posix_spawn() is still violating the standard here?
>
>> No, it still does not pass the posix_spawn() parts of the POSIX
>> VSX-PCTS2003 test suite, for exactly the reasons Glenn listed in his
>> previous email.
>
> spawn iffe tests have been moved to src/lib/libast/features/spawn to make
> monitoring this a bit easier (results in arch/*/src/lib/libast/FEATURE/spawn)
> and the tests have been annotated to list the exact reason for rejecting
> posix_spawn()
>
> src/lib/libast/misc/spawnvex.c was relaxed to use posix_spawn() in some cases
> where _lib_posix_spawn=1 (posix_spawn() works but exits 127 on ENOEXEC)
> sh implementations would use the spawnvex() SPAWN_EXEC flag to disable that
> so they differentiate ENOEXEC from other exec errors -- this means that
> ksh will only use posix_spawn() implementations that iffe _lib_posix_spawn=2
>
> I'll restate why posix_spawn() exit code 127 on ENOEXEC is usesless for sh:
> (1) there is no way for the parent to know how long to wait for the
>     child process exit code check -- how can the shell implement &?
>     * it can't block all other operations waiting for a bad exit status
>     * it can't really proceed with other children -- if 127 comes in later,
>       its too late to retry as a shell script
> (2) exit code 127 is in band -- a user process can exit with that code
>     how can the parent differentiate that?

I don't see how this is useful, too.
But I do not understand why Solaris and the other Unix implementations
have a posix_spawn() implementation which apparently works with
ksh93u+. Why can't the glibc developers just clone this behaviour
(which appears to be mandated by POSIX and the POSIX VSX-PCTS2003 test
suite) and not insist on their world view of posix_spawn() which is so
far away from sanity and doesn't allow the implementation of real
world consumers.

>
> to make the exit 127 implementations useful would require a portable
> posix_is_executable(path) that would do the exec mode/perm checks along
> with the object magic number checks -- a shell implementation would then
> call this before posix_spawn() -- but then how much would this cut into
> the savings of posix_spawn() over [v]fork()/exec()
>

posix_spawn() saves a lot of work in the kernel when it is implemented
as a syscall - it saves all the overhead of a full vfork() and exec()
will require to first create a whole child process with the parents
attributes and then change most of the attributes later. posix_spawn()
creates a whole new child process with the *selected* attributes and
that's all. That's a lot less parent-child communication and traffic.

Ced
-- 
Cedric Blancher <[email protected]>
Institute Pasteur
_______________________________________________
ast-developers mailing list
[email protected]
http://lists.research.att.com/mailman/listinfo/ast-developers

Reply via email to