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]; }