Die "%m", die (was Re: [olsr-dev] [PATCH] Improvements in dot_draw plugin)

Bernd Petrovitsch (spam-protected)
Sun Jan 8 21:00:30 CET 2006


On Fri, 2006-01-06 at 09:54 +0100, Roar Bjørgum Rotvik wrote:
> Bernd Petrovitsch wrote:
> > On Mon, 2005-11-14 at 22:02 +0100, Thomas Lopatic wrote:
> [ ... ]
> > The attached patch against cvs-current kills all %m which are used for
> > printf(), syslog() and the like and replaces them with the above
> > solution.
> > 
> > I also replaced the ones in the Unix-specific directories because
> > - to be able to check if with a simple 
> > find -type f -name '*.[ch]' -print0 | xargs -0r fgrep %m /dev/null
> > - no one should be tempted or able to copy-paste them into "wrong"
> >   files.
> > - it actually fixes bugs since several of them are called after
> >   e.g. OLSR_PRINTF() or perror() and they surely clobber "errno"
> >   anyway.
> 
> I have some comments to this patch.

Good, than someone actually reads it;-)

> You indicate that errno may be clobbered by OLSR_PRINTF() or perror(),
> but look at this description from "man 3 perror" on linux:
> "The error number is taken  from  the external variable errno, which is
> set when errors occur but not cleared when non-erroneous calls are made."
> 
> That means that if a system call returns error code (normally -1), then
> errno is set to new error value. If the functions do not fail and return
> an error code, the errno value is unchanged.
> 
> And by looking at the man page for fprintf (as OLSR_PRINTF uses), it may
> return an negative value but the man page does not specify that the
> errno is changed or set to a spesific value.
> Compare that to the man page of an system call that is known to change
> the errno value, like the read() call:
> "RETURN VALUE
>   ...
>   On error, -1 is returned, and errno is set appropriately. In this case
> it is left unspecified whether the file position (if any) changes."
> 
> Neither the manpages for fprintf() or perror() says that errno is set if
> an error occours, so I don't think that errno is clobbered by these
> functions. Do you know otherwise since you said "they surely clobber
> "errno" anyway"?
>
> If you can prove me wrong I'll accept that :)

It is not a prove in the mathematical sense but:
First you are of course that the manual pages do not explicitly mention
the possible "destruction" of errno.
However, IMHO chances are that fprintf(), perror() and cousins may use a
sys-call like write(2).
And since it is also not explicitly mentioned that errno is preserved
(and at least for the perror() manual page I would assume that if
perror(3) really does never change "errno" it would be mentioned), it
seems safest to me to not assume some special behaviour.

At least uClibc's perror() function does use write(2).
perror() in glibc-2.2.5 (sorry, that source was just handy) just calls
fprintf(3) which simply calls vfprintf(3). And I assume now (since
really delving into glibc source is somwhat cumbersome) that it may
eventually use (in some libc implementation) write(2) or set "errno" for
whatever else fails somewhere in between.

I think with this simple program (the #include's) are missing, I can
simulate a really failing fprintf(3). The mlockall()/munlockall() calls
are there to identify the interesting output easily, if you `strace` it
(but you must be root if you don't want to get errors from these calls):
----  snip  ----
int main(void)
{
  int rv;
  close(STDERR_FILENO);
  mlockall(MCL_CURRENT|MCL_FUTURE);
  rv = fprintf(stderr, "Hello world!\n");
  munlockall();
  return rv;
}
----  snip  ----
Started in a shell (on FC4-current):
----  snip  ----
{25}sudo strace ./fprintf 2>&1 | awk '/mlockall/,/munlockall/'
mlockall(MCL_CURRENT|MCL_FUTURE)        = 0
write(2, "Hello world!\n", 13)          = -1 EBADF (Bad file descriptor)
munlockall()                            = 0
----  snip  ----
At least in this error case, "errno" is clobbered.

You can do the same for a perror(3) version and it looks quite similar
(but funny, perror(2) seems to do dup2() for whatever reason).

Apart from that I can live with your solution too. But I can't really
see an advantage of calling the same function twice (even if it is only
strerror(3)).

	Bernd
-- 
Firmix Software GmbH                   http://www.firmix.at/
mobil: +43 664 4416156                 fax: +43 1 7890849-55
          Embedded Linux Development and Services







More information about the Olsr-dev mailing list