Subject: Re: syslog_r (Re: CVS commit: src/lib/libc)
To: Christos Zoulas <christos@astron.com>
From: Jason Thorpe <thorpej@shagadelic.org>
List: tech-userlevel
Date: 10/27/2006 08:45:47
On Oct 26, 2006, at 12:18 PM, Christos Zoulas wrote:
> So it is really trivial to make syslog_r async-signal-safe in our
> case.
Please, no, because it makes syslog_r(3) lack functionality that syslog
(3) has.
If we REALLY want this logging nonsense in libssp, then write a NEW
LIBRARY CALL that takes only constant strings or something.
(Personally, I think the best thing for such programs is to simply
abort(3) rather than spew messages into the system log.)
>
> First we add a flag in stdio.h:
> Index: stdio.h
> ===================================================================
> RCS file: /cvsroot/src/include/stdio.h,v
> retrieving revision 1.64
> diff -u -u -r1.64 stdio.h
> --- stdio.h 10 May 2006 21:09:45 -0000 1.64
> +++ stdio.h 26 Oct 2006 19:13:57 -0000
> @@ -157,6 +157,7 @@
> #define __SOFF 0x1000 /* set iff _offset is in fact correct */
> #define __SMOD 0x2000 /* true => fgetln modified _p text */
> #define __SALC 0x4000 /* allocate string space dynamically */
> +#define __SAFE 0x8000 /* don't call signal-unsafe functions */
>
> /*
> * The following three definitions are for ANSI C, which took them
>
> Then we use it to avoid calling non-signal-safe functions in vfprintf
> ():
> Index: vfprintf.c
> ===================================================================
> RCS file: /cvsroot/src/lib/libc/stdio/vfprintf.c,v
> retrieving revision 1.50
> diff -u -b -w -u -r1.50 vfprintf.c
> --- vfprintf.c 16 Feb 2006 23:26:19 -0000 1.50
> +++ vfprintf.c 26 Oct 2006 19:10:23 -0000
> @@ -335,6 +335,10 @@
> */
> for (;;) {
> cp = fmt;
> + if (fp->_flags & __SAFE) {
> + for (; *fmt &&*fmt != '%'; fmt++)
> + continue;
> + } else {
> while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
> fmt += n;
> if (wc == '%') {
> @@ -342,6 +346,7 @@
> break;
> }
> }
> + }
> if ((m = fmt - cp) != 0) {
> PRINT(cp, m);
> ret += m;
> @@ -493,7 +498,7 @@
> size = 3;
> break;
> }
> - if (isnan(_double)) {
> + if ((fp->_flags & __SAFE) || isnan(_double)) {
> if (ch == 'E' || ch == 'F' || ch == 'G')
> cp = "NAN";
> else
>
> Finally we provide a snprintf_r() and a vsnprintf_r() [call them
> what you
> wish] wrappers that look like the nor _r functions, but they only do:
>
> fp->_flags |= __SAFE;
>
> Then we can use them in syslog_r(), and everything works as expected.
> Well, floating point numbers print NaN, but...
>
> Opinions?
>
> christos
-- thorpej