X-Git-Url: http://www.dolda2000.com/gitweb/?a=blobdiff_plain;f=lib%2Fcf.c;h=b809d331e051db3255c43b666997052743b2d8cc;hb=832efc978604c4779db85540e3c9c8ee8898d8c9;hp=47db8c235fbfe77a9114152d646c554dbb72b794;hpb=b3eb750fd08c14921d61fe7d31cf861f02a8fc58;p=ashd.git diff --git a/lib/cf.c b/lib/cf.c index 47db8c2..b809d33 100644 --- a/lib/cf.c +++ b/lib/cf.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #ifdef HAVE_CONFIG_H @@ -43,6 +44,8 @@ struct stdchild { char **argv; char **envp; int fd; + int agains; + time_t lastrep; }; static int parsefile(struct cfstate *s, FILE *in); @@ -325,8 +328,10 @@ static char **expandargs(struct stdchild *sd) 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++) { @@ -354,26 +359,35 @@ static char **expandargs(struct stdchild *sd) 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)) { @@ -382,21 +396,32 @@ static int stdhandle(struct child *ch, struct hthead *req, int fd, void (*chinit /* 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); }