children[dname] = util.pchild(["dirplex", path], autorespawn = True)
children[dname].passreq(req)
return
- util.respond(req, "No such host in configured.\n", status = "404 Not Found", ctype = "text/plain")
+ util.respond(req, "No such host is configured.\n", status = "404 Not Found", ctype = "text/plain")
util.serveloop(serve)
set -e
cd "$(dirname "$0")"
-# Start htparser running this dynhosts script. The setsid command
-# ensures that SIGINT is only received by htparser and not by
-# dynhosts; it is not of grave importance, but makes shutdown slightly
-# more clean, and hides the KeyboardInterrupt otherwise raised by
-# Python.
-htparser plain:port=8080 -- setsid ./dynhosts .
+# Start htparser running this dynhosts script.
+htparser plain:port=8080 -- ./dynhosts .
# Invoke dirplex running in this directory, loading the wsgidir.rc
# configuration file. The same configuration can be put in
# e.g. /etc/ashd/dirplex.d or in any .htrc file.
-
-# The setsid command ensures that SIGINT is only received by htparser
-# and not by dirplex or its children; it is not of any importance, but
-# makes shutdown slightly cleaner, and hides the KeyboardInterrupt
-# otherwise raised by Python.
-htparser plain:port=8080 -- setsid dirplex -c ./wsgidir.rc .
+htparser plain:port=8080 -- dirplex -c ./wsgidir.rc .
#include <ctype.h>
#include <glob.h>
#include <libgen.h>
+#include <sys/socket.h>
#include <errno.h>
#ifdef HAVE_CONFIG_H
static int stdhandle(struct child *ch, struct hthead *req, int fd, void (*chinit)(void *), void *idata)
{
struct stdchild *i = ch->pdata;
+ int serr;
if(i->type == CH_SOCKET) {
if(i->fd < 0)
i->fd = stdmkchild(i->argv, chinit, idata);
- if(sendreq(i->fd, req, fd)) {
- if((errno == EPIPE) || (errno == ECONNRESET)) {
+ if(sendreq2(i->fd, req, fd, MSG_NOSIGNAL | MSG_DONTWAIT)) {
+ serr = errno;
+ if((serr == EPIPE) || (serr == ECONNRESET)) {
/* Assume that the child has crashed and restart it. */
close(i->fd);
i->fd = stdmkchild(i->argv, chinit, idata);
- if(!sendreq(i->fd, req, fd))
+ if(!sendreq2(i->fd, req, fd, MSG_NOSIGNAL | MSG_DONTWAIT))
return(0);
}
- flog(LOG_ERR, "could not pass on request to child %s: %s", ch->name, strerror(errno));
- close(i->fd);
- i->fd = -1;
+ flog(LOG_ERR, "could not pass on request to child %s: %s", ch->name, strerror(serr));
+ if(serr != EAGAIN) {
+ close(i->fd);
+ i->fd = -1;
+ }
return(-1);
}
} else if(i->type == CH_FORK) {
int sendfd(int sock, int fd, char *data, size_t datalen)
{
- return(sendfd2(sock, fd, data, datalen, MSG_NOSIGNAL | MSG_DONTWAIT));
+ return(sendfd2(sock, fd, data, datalen, MSG_NOSIGNAL));
}
int recvfd(int sock, char **data, size_t *datalen)
int sendreq(int sock, struct hthead *req, int fd)
{
- return(sendreq2(sock, req, fd, MSG_NOSIGNAL | MSG_DONTWAIT));
+ return(sendreq2(sock, req, fd, MSG_NOSIGNAL));
}
int recvreq(int sock, struct hthead **reqp)
{
vavar(int, fd);
char *buf;
- int i, ret;
+ int i, s, ret;
+ s = 0;
while(1) {
if(block(fd, EV_READ, 0) == 0)
break;
flog(LOG_WARNING, "received error on rootplex read channel: %s", strerror(errno));
exit(1);
} else if(ret == 0) {
+ s = 1;
free(buf);
break;
}
* some day... */
free(buf);
}
- close(plex);
- plex = -1;
+ shutdown(plex, SHUT_RDWR);
for(i = 0; i < listeners.d; i++) {
if(listeners.b[i] == muth)
bufdel(listeners, i);
}
- flog(LOG_INFO, "root handler exited, so shutting down listening...");
- while(listeners.d > 0)
- resume(listeners.b[0], 0);
+ if(s) {
+ flog(LOG_INFO, "root handler exited, so shutting down listening...");
+ while(listeners.d > 0)
+ resume(listeners.b[0], 0);
+ }
}
static void initroot(void *uu)
static void serve2(struct user *usr, struct hthead *req, int fd)
{
+ int serr;
+
if(usr->fd < 0)
usr->fd = forkchild(usr->name, req, fd);
- if(sendreq(usr->fd, req, fd)) {
- if((errno == EPIPE) || (errno == ECONNRESET)) {
+ if(sendreq2(usr->fd, req, fd, MSG_NOSIGNAL | MSG_DONTWAIT)) {
+ serr = errno;
+ if((serr == EPIPE) || (serr == ECONNRESET)) {
/* Assume that the child has crashed and restart it. */
close(usr->fd);
usr->fd = forkchild(usr->name, req, fd);
- if(!sendreq(usr->fd, req, fd))
+ if(!sendreq2(usr->fd, req, fd, MSG_NOSIGNAL | MSG_DONTWAIT))
return;
}
- flog(LOG_ERR, "could not pass on request to user `%s': %s", usr->name, strerror(errno));
- close(usr->fd);
- usr->fd = -1;
+ flog(LOG_ERR, "could not pass on request to user `%s': %s", usr->name, strerror(serr));
+ if(serr != EAGAIN) {
+ close(usr->fd);
+ usr->fd = -1;
+ }
}
}