On Mon, 2005-08-22 at 14:24 +0200, Paul J Stevens wrote:
> > I'm not sure why sprintf would call malloc... but looking at the glibc
> > code, it gets called quite a lot! Looks like they're fully preparing the
> > strings before any output happens, rather than output-on-the-fly.

The glibc people are big into doing a lot of useless shit. I think they
think malloc() grows on trees, or that it's cheap or something.

It's really sick when glibc provides an alloca() that's not as good as
the GNUC alloca() ;/


> > I wonder if we should have a function like trace_static() that either
> > doesn't use a formatstring, or for which we write our own printf-style
> > format code. Using a static buffer and/or byte-at-a-time output, we can
> > avoid malloc.

Bah. Steal it. 

http://www.fefe.de/dietlibc/
lib/__v_printf.c is a perfectly fine s/snprintf implementation that
doesn't allocate memory.


In general, I try to avoid STDIO... see below.

> I'm now doing:

Don't do that. I brought this up before: signal handlers should do as
little as possible. About the only thing universally "safe" to do inside
a signal handler is:
        * write to a pipe nonblocking
        * change a volatile int
Many system calls and most library calls aren't safe. I provided the
list a complete (ahem) list a while back.

Attached is what I do for signal handlers. I call sigh(SIGCHLD) or
whatever and put the returned fd into my select() loop. It happens at
some point- and AT that point, I can invoke whatever I like.

In general, the fgets/fread/fgetc() junk on sockets, although
convenient, is extremely dangerous. Fortunately, because dbmail is
otherwise a blocking server, blocking on these things is really really
easy.

Again, dietlibc has some excellent stdio implemention code that'd make
this easier.

Don't get too fancy if you decide to roll your own, the most trivial
[but correct] readline implementation:
        char *q;
        int x;
        memcpy(bigbuffer, bigsecond, sizeof(bigsecond));
        x = bigsecond_x;
        r = read(fd, bigbuffer+x, sizeof(bigbuffer)-x);
        if (r < 1) return 0;
        r += x;
        q = memchr(bigbuffer, '\n', r);
        if (q) {
                memcpy(bigsecond, q, sizeof(bigbuffer)-(q-bigbuffer));
                bigsecond_x = q - bigbuffer;
                return bigbuffer;
        }
        if (r == sizeof(bigbuffer)) {
                /* buffer too small to hold an entire line */
                return 0;
        }
        memcpy(bigsecond, bigbuffer, r);
        bigsecond_x = r;
        return 0; /* need more */

is actually fast enough for anything dbmail is going to do, and loads
faster than the fgets() on most systems.

With this, before calling read() do a select() on fd and the sigh
returnees.

Note: I didn't test the readline function. If you want a good one, let
me know :)

-- 
Internet Connection High Quality Web Hosting
http://www.internetconnection.net/
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>

/* FIXME: SIGRTMAX <= 255 */
static int _sigh_fd[255] = {-1};

void _sigh_e(int n)
{
	int f = _sigh_fd[n];
	int r;
	r = fcntl(f, F_GETFL, 0);
	if (!(r&O_NONBLOCK)) fcntl(f, F_SETFL, r|O_NONBLOCK);
	(void)write(f, "", 1);
	if (!(r&O_NONBLOCK)) fcntl(f, F_SETFL, r);
}
int sigh(int signo)
{
	int p[2];
	if (pipe(p) == -1) return -1;
	if (_sigh_fd[signo] > -1) (void)close(_sigh_fd[signo]);
	_sigh_fd[signo] = p[0];
	signal(signo, _sigh_e);
	return p[1];
}

Reply via email to