m4-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: sysval and doc fixes


From: Eric Blake
Subject: Re: sysval and doc fixes
Date: Wed, 21 Jun 2006 06:57:46 -0600
User-agent: Thunderbird 1.5.0.4 (Windows/20060516)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Gary,

According to Gary V. Vaughan on 6/21/2006 5:44 AM:
> Hi Eric!
> 
>> And if system() fails with -1 (such as for E2BIG, when I exceed the 1MB
>> ARG_MAX limitation), Solaris still translated that to 127:
>> $ perl -e 'print "syscmd(/bin/echo ".("a "x2000000).")sysval"' |\
>> /usr/ccs/bin/m4 -B5000000
>> 127
> 
> $ config.guess
> i686-pc-linux-gnu
> $ perl -e 'print "syscmd(/bin/echo ".("a "x2000000).")sysval"' | m4
> 127
> 
> But that is due to:
> 
> RETURN VALUE
>        The value returned is -1 on error (e.g.  fork() failed), and the return
>        status  of  the command otherwise.  This latter return status is in the
>        format specified in wait(2).  Thus, the exit code of the  command  will
>        be  WEXITSTATUS(status).   In  case  /bin/sh could not be executed, the
>        exit status will be that of a command that does exit(127).
> 
> ...which may not be true of all platform the GNU M4 builds on.

Hmm, POSIX has this to say about it:
If some error prevents the command language interpreter from executing
after the child process is created, the return value from system() shall
be as if the command language interpreter had terminated using exit(127)
or _exit(127). If a child process cannot be created, or if the termination
status for the command language interpreter cannot be obtained, system()
shall return -1 and set errno to indicate the error.

So I guess in the above case, Solaris successfully did a vfork() but then
failed to exec /bin/sh, explaining the 127.  I don't really know an easy
way to force a fork() failure on Solaris, to see if I could make sysval
display 255 or -1.  So maybe it's okay if sysval returns -1 if system()
did likewise.

> 
>> But the GNU version wasn't even checking for failure on syscmd, and only
>> partially on esyscmd, with a result of 255 on failure.
> 
> Nice catch :-)
> 
> In theory, this means we can't tell the the difference between a system
> call failure and killed by signal 127 (TERMSIG is status&0x7f)... but
> this is definitely an improvement, so please commit after taking my comments
> below into consideration.

Except that most systems don't support 127 signals, and by the patch
below, a signal of 127, if supported, would result in 32512.  But yes, it
is not possible to tell between a program that exited normally with status
127 and a program that was unable to be executed.

> 
>> 2006-06-20  Eric Blake  <address@hidden>
>>
>>      For compatibility with other m4 implementations, sysval returns
>>      signal*256 rather than 0 if syscmd is terminated by signal.
> 
> I would call this signal<<8 to make it clearer that the signal number
> bitpattern is not changed.

Good idea.

> Please port forward too :-)

It's on my (growing) list.

> 
> We can simplify the changes to src/builtin.c, and remove some redundancy.
> And fix an uninitialised variable if sysval is expanded before syscmd
> is used:
> 
> 
> #ifndef WEXITSTATUS
> # define WEXITSTATUS(status) (((status) >> 8) & 0xff)
> #endif
> #ifndef WTERMSIG
> # define WTERMSIG(status) ((status) & 0x7f)
> #endif

Except that POSIX states that WEXITSTATUS is undefined if WIFEXITED is
false (likewise for WIFSIGNALED/WTERMSIG); we really do need all 4 to be
portable.

> 
> /* Exit code from last "syscmd" command.  */
> static int sysval = 0;

That's redundant.  Uninitialized static variables live in .bss and are
0-initialized by the C runtime (it is only the heap and uninitialized
local variables that have garbage values).  Even with 1.4.4:
$ echo sysval|m4
0

But it does beg the question - should frozen files preserve sysval?  It's
not worth changing this for 1.4.x, but we should probably add another
command to frozen file format 2 in m4-2.0 to preserve nonzero sysval over
freezing.


> 
> ...
> 
> static void
> m4_sysval (struct obstack *obs, int argc, token_data **argv)
> {
>   /* If previous syscmd call exited, SYSVAL is the exit status;
>      if syscmd was killed by a signal, SYSVAL is signal number times 256,
>      if syscmd could not execute command, SYSVAL is 127,
>      else SYSVAL is 0 */
>   shipout_int (obs, sysval == -1
>                       ? 0x7f
>                       : ((WEXITSTATUS (sysval))|(WTERMSIG (sysval) << 8)));
> }

OK, I can keep the decode logic factored in m4_sysval, rather than
duplicating in m4_e?syscmd.

> 
> Cheers,
>       Gary.

- --
Life is short - so eat dessert first!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEmUJJ84KuGfSFAYARArvcAJ4r5tLxxxgvTJo81L+WdMvPNe3kmQCgnlhO
HZgW2M/IPzUeOS7EO6rNqvY=
=dOop
-----END PGP SIGNATURE-----




reply via email to

[Prev in Thread] Current Thread [Next in Thread]