#include <glob.h>
#include <libgen.h>
#include <sys/socket.h>
+#include <time.h>
#include <errno.h>
#ifdef HAVE_CONFIG_H
char **argv;
char **envp;
int fd;
+ int agains;
+ time_t lastrep;
};
static int parsefile(struct cfstate *s, FILE *in);
for(p2 = sd->argv[i]; p != NULL; p2 = np, p = strchr(np, '$')) {
bufcat(exp, p2, p - p2);
if(p[1] == '{') {
- if((p3 = strchr((p += 2), '}')) == NULL)
+ if((p3 = strchr((p += 2), '}')) == NULL) {
+ np = p;
break;
+ }
np = p3 + 1;
} else {
for(p3 = ++p; *p3; p3++) {
return(ret);
}
-static int stdhandle(struct child *ch, struct hthead *req, int fd, void (*chinit)(void *), void *idata)
+struct sidata {
+ struct stdchild *sd;
+ void (*sinit)(void *);
+ void *sdata;
+};
+
+static void stdinit(void *data)
+{
+ struct sidata *d = data;
+ int i;
+
+ for(i = 0; d->sd->envp[i]; i += 2)
+ putenv(sprintf2("%s=%s", d->sd->envp[i], d->sd->envp[i + 1]));
+ if(d->sinit != NULL)
+ d->sinit(d->sdata);
+}
+
+static int stdhandle(struct child *ch, struct hthead *req, int fd, void (*chinit)(void *), void *sdata)
{
struct stdchild *sd = ch->pdata;
int serr;
char **args;
-
- void stdinit(void *data)
- {
- int i;
-
- for(i = 0; sd->envp[i]; i += 2)
- putenv(sprintf2("%s=%s", sd->envp[i], sd->envp[i + 1]));
- if(chinit != NULL)
- chinit(data);
- }
+ struct sidata idat;
if(sd->type == CH_SOCKET) {
+ idat = (struct sidata) {.sd = sd, .sinit = chinit, .sdata = sdata};
if(sd->fd < 0) {
args = expandargs(sd);
- sd->fd = stdmkchild(args, stdinit, idata);
+ sd->fd = stdmkchild(args, stdinit, &idat);
freeca(args);
}
if(sendreq2(sd->fd, req, fd, MSG_NOSIGNAL | MSG_DONTWAIT)) {
/* Assume that the child has crashed and restart it. */
close(sd->fd);
args = expandargs(sd);
- sd->fd = stdmkchild(args, stdinit, idata);
+ sd->fd = stdmkchild(args, stdinit, &idat);
freeca(args);
if(!sendreq2(sd->fd, req, fd, MSG_NOSIGNAL | MSG_DONTWAIT))
- return(0);
+ goto ok;
+ serr = errno;
}
- flog(LOG_ERR, "could not pass on request to child %s: %s", ch->name, strerror(serr));
- if(serr != EAGAIN) {
+ if(serr == EAGAIN) {
+ if(sd->agains++ == 0) {
+ flog(LOG_WARNING, "request to child %s denied due to buffer overload", ch->name);
+ sd->lastrep = time(NULL);
+ }
+ } else {
+ flog(LOG_ERR, "could not pass on request to child %s: %s", ch->name, strerror(serr));
close(sd->fd);
sd->fd = -1;
}
return(-1);
}
+ ok:
+ if((sd->agains > 0) && ((time(NULL) - sd->lastrep) > 10)) {
+ flog(LOG_WARNING, "%i requests to child %s were denied due to buffer overload", sd->agains, ch->name);
+ sd->agains = 0;
+ }
} else if(sd->type == CH_FORK) {
args = expandargs(sd);
- if(stdforkserve(args, req, fd, chinit, idata) < 0) {
+ if(stdforkserve(args, req, fd, chinit, sdata) < 0) {
freeca(args);
return(-1);
}