From 0717109bc9228681c931ccc461167dd22f302f28 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Sat, 29 Jul 2023 01:54:15 +0200 Subject: [PATCH 01/16] ratequeue: Add some missing includes. --- src/ratequeue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ratequeue.c b/src/ratequeue.c index aa57b26..21d6ec3 100644 --- a/src/ratequeue.c +++ b/src/ratequeue.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #ifdef HAVE_CONFIG_H -- 2.20.1 From 0bde126e02214a57138e4450367b7cc38510363e Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Sat, 29 Jul 2023 01:54:26 +0200 Subject: [PATCH 02/16] htpipe: Add some missing includes. --- src/htpipe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/htpipe.c b/src/htpipe.c index 27e5480..02cbd35 100644 --- a/src/htpipe.c +++ b/src/htpipe.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include -- 2.20.1 From 5a723273828ffc7b3889e538344c65cc15eb3696 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Wed, 9 Aug 2023 19:11:33 +0200 Subject: [PATCH 03/16] accesslog: Add %p and %P format options. --- doc/accesslog.doc | 11 +++++++++++ src/accesslog.c | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/doc/accesslog.doc b/doc/accesslog.doc index 2baf508..7a8e8e9 100644 --- a/doc/accesslog.doc +++ b/doc/accesslog.doc @@ -199,6 +199,17 @@ instead expand into a dash. Expands into the time it took for the handler to complete the response, expressed as seconds with 6 decimals precision. +*%{*'HEADER'*}p*:: + + Expands into the HTTP response header named by 'HEADER'. If + the specified header does not exist in the request, *%p* + expands into a dash. + +*%{*'HEADER'*}P*:: + + Similar to *%p*, except that 'HEADER' is prepended with + `X-Ash-`, for simple convenience. + In any expanded field, any "unsafe" characters are escaped. Currently, this means that double-quotes and backslashes are prepended with a backslash, newlines and tabs are expressed as, respectively, `\n` and diff --git a/src/accesslog.c b/src/accesslog.c index af43373..7c550dd 100644 --- a/src/accesslog.c +++ b/src/accesslog.c @@ -96,6 +96,16 @@ static void logitem(struct logdata *data, char o, char *d) qputs(h, out); } break; + case 'p': + if(!data->resp || ((h = getheader(data->req, d)) == NULL)) { + putc('-', out); + } else { + qputs(h, out); + } + break; + case 'P': + logitem(data, 'p', sprintf3("X-Ash-%s", d)); + break; case 'u': qputs(data->req->url, out); break; -- 2.20.1 From 5db75597d67ca7830e20c1ca2fabb20f542ae336 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Wed, 9 Aug 2023 19:14:12 +0200 Subject: [PATCH 04/16] accesslog: Add standard response header for logging user info. --- src/accesslog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/accesslog.c b/src/accesslog.c index 7c550dd..e419587 100644 --- a/src/accesslog.c +++ b/src/accesslog.c @@ -518,7 +518,7 @@ int main(int argc, char **argv) pidfile = optarg; break; case 'a': - format = "%A - - [%{%d/%b/%Y:%H:%M:%S %z}t] \"%m %u %v\" %c %o \"%R\" \"%G\""; + format = "%A - %{log-user}P [%{%d/%b/%Y:%H:%M:%S %z}t] \"%m %u %v\" %c %o \"%R\" \"%G\""; break; default: usage(stderr); -- 2.20.1 From a7d7286d8de39daaf90952eeea77e5e83d598eae Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Wed, 9 Aug 2023 19:23:52 +0200 Subject: [PATCH 05/16] accesslog: Fix %p bug. --- src/accesslog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/accesslog.c b/src/accesslog.c index e419587..0c7ef8d 100644 --- a/src/accesslog.c +++ b/src/accesslog.c @@ -97,7 +97,7 @@ static void logitem(struct logdata *data, char o, char *d) } break; case 'p': - if(!data->resp || ((h = getheader(data->req, d)) == NULL)) { + if(!data->resp || ((h = getheader(data->resp, d)) == NULL)) { putc('-', out); } else { qputs(h, out); -- 2.20.1 From eaefded0a959b59f441d50cfb30fc08497078fe1 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Thu, 10 Aug 2023 13:18:22 +0200 Subject: [PATCH 06/16] python3: Encode ashd-wsgi3 output headers with utf-8 instead of latin-1. --- python3/ashd-wsgi3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python3/ashd-wsgi3 b/python3/ashd-wsgi3 index 2ca259a..c10bfc9 100755 --- a/python3/ashd-wsgi3 +++ b/python3/ashd-wsgi3 @@ -151,7 +151,7 @@ def recode(thing): if isinstance(thing, collections.abc.ByteString): return thing else: - return str(thing).encode("latin-1") + return str(thing).encode("utf-8") class request(ashd.serve.wsgirequest): def __init__(self, *, bkreq, **kw): -- 2.20.1 From fdf5e4964c041a4214f36e99a33411cb8058866e Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Thu, 23 Nov 2023 19:53:06 +0100 Subject: [PATCH 07/16] etc: Add environment option to run init.d/ashd silently. --- etc/debian/init.d-ashd | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/etc/debian/init.d-ashd b/etc/debian/init.d-ashd index 9ef1568..d3738a1 100755 --- a/etc/debian/init.d-ashd +++ b/etc/debian/init.d-ashd @@ -26,11 +26,11 @@ ROOTSPEC="dirplex /srv/www" start() { export LANG - log_daemon_msg "Starting HTTP server" "ashd" + [ -n "$SILENT_INIT" ] || log_daemon_msg "Starting HTTP server" "ashd" if start-stop-daemon -S -p "$PIDFILE" -qa "$HTPARSER" -- -Sf -p "$PIDFILE" -u "$USER" -r "$CHROOT" $PORTSPEC -- $ROOTSPEC; then - log_success_msg + [ -n "$SILENT_INIT" ] || log_success_msg else - log_end_msg $? + [ -n "$SILENT_INIT" ] || log_end_msg 1 fi } @@ -48,7 +48,7 @@ kill_listen() { log_failure_msg "invalid saved pid" return 1 fi - log_progress_msg "listen" + [ -n "$SILENT_INIT" ] || log_progress_msg "listen" kill -TERM "$pid" for try in 0 1 2 3 4 5; do sleep $try @@ -68,36 +68,39 @@ kill_listen() { } stop_listen() { - log_daemon_msg "Stopping HTTP server" "ashd" - kill_listen - log_end_msg $? + [ -n "$SILENT_INIT" ] || log_daemon_msg "Stopping HTTP server" "ashd" + if kill_listen; then + [ -n "$SILENT_INIT" ] || log_success_msg + else + [ -n "$SILENT_INIT" ] || log_end_msg $? + fi } stop_gracefully() { - log_daemon_msg "Stopping HTTP server" "ashd" + [ -n "$SILENT_INIT" ] || log_daemon_msg "Stopping HTTP server" "ashd" if ! kill_listen ; then - log_end_msg $? + log_end_msg 1 return 1 fi pid=$(cat "$PIDFILE" 2>/dev/null || true) if kill -0 "$pid" 2>/dev/null; then - log_progress_msg "waiting for remaining connections..." + [ -n "$SILENT_INIT" ] || log_progress_msg "waiting for remaining connections..." for try in $(seq "$GRACE_PERIOD"); do sleep 1 if ! kill -0 "$pid" 2>/dev/null; then - log_success_msg + [ -n "$SILENT_INIT" ] || log_success_msg return 0 fi done else - log_success_msg + [ -n "$SILENT_INIT" ] || log_success_msg return 0 fi - log_progress_msg "terminating remaining connections" + [ -n "$SILENT_INIT" ] || log_progress_msg "terminating remaining connections" if kill_wholly; then - log_success_msg + [ -n "$SILENT_INIT" ] || log_success_msg else - log_end_msg $? + log_end_msg 1 fi } -- 2.20.1 From 19bb68ac652306d1426e6f35674e6d7a2fbe5d8f Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Wed, 12 Jun 2024 00:19:21 +0200 Subject: [PATCH 08/16] python3: Fix ByteString reference in perf module. --- python3/ashd/perf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python3/ashd/perf.py b/python3/ashd/perf.py index 86fe43c..4adfc54 100644 --- a/python3/ashd/perf.py +++ b/python3/ashd/perf.py @@ -1,4 +1,4 @@ -import collections +import collections.abc try: import pdm.perf except: @@ -56,7 +56,7 @@ class request(object): try: if len(self.resp) > 0: status = self.resp[0] - if isinstance(status, collections.ByteString): + if isinstance(status, collections.abc.ByteString): status = status.decode("latin-1") else: status = str(status) -- 2.20.1 From caf363d10985dd372f0a7654fac7cfbfd0cc9dde Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Sat, 31 Aug 2024 16:25:40 +0200 Subject: [PATCH 09/16] ratequeue: Fix rehash bug. --- src/ratequeue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ratequeue.c b/src/ratequeue.c index 21d6ec3..a05187a 100644 --- a/src/ratequeue.c +++ b/src/ratequeue.c @@ -160,6 +160,7 @@ static void rehash(int nlen) if(nlen <= SBUCKETS) { nlen = SBUCKETS; new = sbuckets; + memset(sbuckets, 0, sizeof(sbuckets)); } else { new = szmalloc(sizeof(*new) * (1 << nlen)); } -- 2.20.1 From f905ca5d7cbaf53e638c005765f92d06438f6442 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Sat, 31 Aug 2024 16:29:22 +0200 Subject: [PATCH 10/16] ratequeue: Fix rehash bug again. --- src/ratequeue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ratequeue.c b/src/ratequeue.c index a05187a..c349f18 100644 --- a/src/ratequeue.c +++ b/src/ratequeue.c @@ -160,12 +160,13 @@ static void rehash(int nlen) if(nlen <= SBUCKETS) { nlen = SBUCKETS; new = sbuckets; - memset(sbuckets, 0, sizeof(sbuckets)); } else { new = szmalloc(sizeof(*new) * (1 << nlen)); } if(nlen == hashlen) return; + if(new == sbuckets) + memset(sbuckets, 0, sizeof(sbuckets)); assert(old != new); pl = 1 << hashlen; nl = 1 << nlen; m = nl - 1; for(i = 0; i < pl; i++) { -- 2.20.1 From 54720222d4af3825cb1c63e52d824dda1e360e2b Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Sat, 31 Aug 2024 16:56:36 +0200 Subject: [PATCH 11/16] ratequeue: Improve rehash implementation. --- src/ratequeue.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ratequeue.c b/src/ratequeue.c index c349f18..3d2e6d9 100644 --- a/src/ratequeue.c +++ b/src/ratequeue.c @@ -161,12 +161,11 @@ static void rehash(int nlen) nlen = SBUCKETS; new = sbuckets; } else { - new = szmalloc(sizeof(*new) * (1 << nlen)); + new = smalloc(sizeof(*new) * (1 << nlen)); } if(nlen == hashlen) return; - if(new == sbuckets) - memset(sbuckets, 0, sizeof(sbuckets)); + memset(new, 0, sizeof(*new) * (1 << nlen)); assert(old != new); pl = 1 << hashlen; nl = 1 << nlen; m = nl - 1; for(i = 0; i < pl; i++) { -- 2.20.1 From 5fe32d598fa96b97d7a281bb4dfefd6986ed52b8 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Sun, 20 Oct 2024 15:57:37 +0200 Subject: [PATCH 12/16] Use sys/xattr.h instead of attr/xattr.h. --- configure.ac | 2 +- src/psendfile.c | 2 +- src/sendfile.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 5f2d06b..fcecf84 100644 --- a/configure.ac +++ b/configure.ac @@ -84,7 +84,7 @@ if test -z "$HAS_XATTR"; then AC_CHECK_LIB(attr, getxattr, [:], [HAS_XATTR=no]) fi if test -z "$HAS_XATTR"; then - AC_CHECK_HEADER(attr/xattr.h, [], [HAS_XATTR=no]) + AC_CHECK_HEADER(sys/xattr.h, [], [HAS_XATTR=no]) fi if test "$HAS_XATTR" != no; then HAS_XATTR=yes; fi if test "$with_xattr" = yes -a "$HAS_XATTR" = no; then diff --git a/src/psendfile.c b/src/psendfile.c index 464440a..ae5f7d2 100644 --- a/src/psendfile.c +++ b/src/psendfile.c @@ -42,7 +42,7 @@ #include #ifdef HAVE_XATTR -#include +#include #endif static magic_t cookie; diff --git a/src/sendfile.c b/src/sendfile.c index 85ea9bb..3a81e80 100644 --- a/src/sendfile.c +++ b/src/sendfile.c @@ -37,7 +37,7 @@ #include #ifdef HAVE_XATTR -#include +#include #endif static magic_t cookie = NULL; -- 2.20.1 From 7d88babb6f33b528eb8410c7e496448f2657d9c2 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Mon, 12 May 2025 17:37:31 +0200 Subject: [PATCH 13/16] call[fs]cgi: Fix handler connect blocking bug. --- src/callfcgi.c | 2 +- src/callscgi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/callfcgi.c b/src/callfcgi.c index 8d33eef..83a6c7c 100644 --- a/src/callfcgi.c +++ b/src/callfcgi.c @@ -253,7 +253,7 @@ static int sconnect(void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); while(1) { if(connect(fd, curaddr, caddrlen)) { - if(errno == EINPROGRESS) { + if((errno == EINPROGRESS) || (errno == EAGAIN)) { block(fd, EV_WRITE, 30); errlen = sizeof(err); if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) || ((errno = err) != 0)) { diff --git a/src/callscgi.c b/src/callscgi.c index 2483c49..60c72ac 100644 --- a/src/callscgi.c +++ b/src/callscgi.c @@ -240,7 +240,7 @@ static int sconnect(void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); while(1) { if(connect(fd, curaddr, caddrlen)) { - if(errno == EINPROGRESS) { + if((errno == EINPROGRESS) || (errno == EAGAIN)) { block(fd, EV_WRITE, 30); errlen = sizeof(err); if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) || ((errno = err) != 0)) { -- 2.20.1 From 8bff711bd88d36c8600bfd7504b47a6c56a1d3f6 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Mon, 12 May 2025 17:59:39 +0200 Subject: [PATCH 14/16] call[fs]cgi: At least for now, simply block when connecting to handler. It's not optimal, but the naive mtio implementation has the thundering-herd problem, and this also creates a natural choke-point, transmitting the request buffering responsibility to the parent handler where it belongs. The more ideal solution would probably be to let running requests continue being handled while serializing receving incoming requests and connecting to the request handler. --- src/callfcgi.c | 23 +++++------------------ src/callscgi.c | 23 +++++------------------ 2 files changed, 10 insertions(+), 36 deletions(-) diff --git a/src/callfcgi.c b/src/callfcgi.c index 83a6c7c..8ff0eff 100644 --- a/src/callfcgi.c +++ b/src/callfcgi.c @@ -246,27 +246,14 @@ static void startnolisten(void) static int sconnect(void) { int fd; - int err; - socklen_t errlen; fd = socket(cafamily, SOCK_STREAM, 0); - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); - while(1) { - if(connect(fd, curaddr, caddrlen)) { - if((errno == EINPROGRESS) || (errno == EAGAIN)) { - block(fd, EV_WRITE, 30); - errlen = sizeof(err); - if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) || ((errno = err) != 0)) { - close(fd); - return(-1); - } - return(fd); - } - close(fd); - return(-1); - } - return(fd); + if(connect(fd, curaddr, caddrlen)) { + close(fd); + return(-1); } + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + return(fd); } static int econnect(void) diff --git a/src/callscgi.c b/src/callscgi.c index 60c72ac..ee46ac1 100644 --- a/src/callscgi.c +++ b/src/callscgi.c @@ -233,27 +233,14 @@ static void startnolisten(void) static int sconnect(void) { int fd; - int err; - socklen_t errlen; fd = socket(cafamily, SOCK_STREAM, 0); - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); - while(1) { - if(connect(fd, curaddr, caddrlen)) { - if((errno == EINPROGRESS) || (errno == EAGAIN)) { - block(fd, EV_WRITE, 30); - errlen = sizeof(err); - if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) || ((errno = err) != 0)) { - close(fd); - return(-1); - } - return(fd); - } - close(fd); - return(-1); - } - return(fd); + if(connect(fd, curaddr, caddrlen)) { + close(fd); + return(-1); } + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + return(fd); } static int econnect(void) -- 2.20.1 From 99587986310c564757f0c8a15a44b74b98fc7898 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Tue, 13 May 2025 03:11:27 +0200 Subject: [PATCH 15/16] lib: Allow mtio block to take no file descriptor, allowing threads to just sleep. --- lib/mtio-epoll.c | 2 ++ lib/mtio-kqueue.c | 2 ++ lib/mtio-select.c | 30 +++++++++++++++++------------- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/mtio-epoll.c b/lib/mtio-epoll.c index f4c4970..4636873 100644 --- a/lib/mtio-epoll.c +++ b/lib/mtio-epoll.c @@ -53,6 +53,8 @@ static int regfd(struct blocker *bl) struct blocker *o; struct epoll_event evd; + if(bl->fd < 0) + return(0); memset(&evd, 0, sizeof(evd)); evd.events = 0; if(bl->ev & EV_READ) diff --git a/lib/mtio-kqueue.c b/lib/mtio-kqueue.c index 7d086e2..a821688 100644 --- a/lib/mtio-kqueue.c +++ b/lib/mtio-kqueue.c @@ -54,6 +54,8 @@ static int regfd(struct blocker *bl) int prev; struct kevent evd; + if(bl->fd < 0) + return(0); if(bl->fd >= fdln) { if(fdlist) { fdlist = srealloc(fdlist, sizeof(*fdlist) * (bl->fd + 1)); diff --git a/lib/mtio-select.c b/lib/mtio-select.c index e0a4177..167bd6f 100644 --- a/lib/mtio-select.c +++ b/lib/mtio-select.c @@ -137,13 +137,15 @@ int ioloop(void) now = time(NULL); timeout = 0; for(bl = blockers; bl; bl = bl->n) { - if(bl->ev & EV_READ) - FD_SET(bl->fd, &rfds); - if(bl->ev & EV_WRITE) - FD_SET(bl->fd, &wfds); - FD_SET(bl->fd, &efds); - if(bl->fd > maxfd) - maxfd = bl->fd; + if(bl->fd >= 0) { + if(bl->ev & EV_READ) + FD_SET(bl->fd, &rfds); + if(bl->ev & EV_WRITE) + FD_SET(bl->fd, &wfds); + FD_SET(bl->fd, &efds); + if(bl->fd > maxfd) + maxfd = bl->fd; + } if((bl->to != 0) && ((timeout == 0) || (timeout > bl->to))) timeout = bl->to; } @@ -165,12 +167,14 @@ int ioloop(void) if((it.bl = bl->n) != NULL) it.bl->it = ⁢ ev = 0; - if(FD_ISSET(bl->fd, &rfds)) - ev |= EV_READ; - if(FD_ISSET(bl->fd, &wfds)) - ev |= EV_WRITE; - if(FD_ISSET(bl->fd, &efds)) - ev = -1; + if(bl->fd >= 0) { + if(FD_ISSET(bl->fd, &rfds)) + ev |= EV_READ; + if(FD_ISSET(bl->fd, &wfds)) + ev |= EV_WRITE; + if(FD_ISSET(bl->fd, &efds)) + ev = -1; + } if((ev < 0) || (ev & bl->ev)) { if(bl->id < 0) { resume(bl->th, ev); -- 2.20.1 From b3e496789125b6a34662b30ec1ae2a15ef501011 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Tue, 13 May 2025 03:16:55 +0200 Subject: [PATCH 16/16] call[fs]cgi: Handle serialized child connections asynchronously. --- src/callfcgi.c | 32 ++++++++++++++++++++++++++------ src/callscgi.c | 32 ++++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/callfcgi.c b/src/callfcgi.c index 8ff0eff..100788c 100644 --- a/src/callfcgi.c +++ b/src/callfcgi.c @@ -246,14 +246,30 @@ static void startnolisten(void) static int sconnect(void) { int fd; + int err; + socklen_t errlen; fd = socket(cafamily, SOCK_STREAM, 0); - if(connect(fd, curaddr, caddrlen)) { + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + while(1) { + if(!connect(fd, curaddr, caddrlen)) + return(fd); + if(errno == EAGAIN) { + block(-1, 0, 1); + continue; + } + if(errno == EINPROGRESS) { + block(fd, EV_WRITE, 30); + errlen = sizeof(err); + if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) || ((errno = err) != 0)) { + close(fd); + return(-1); + } + return(fd); + } close(fd); return(-1); } - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); - return(fd); } static int econnect(void) @@ -676,7 +692,6 @@ static void serve(struct muth *muth, va_list args) size_t read; char buf[8192]; - sfd = reconn(); is = mtstdopen(fd, 1, 60, "r+", NULL); os = mtstdopen(sfd, 1, 600, "r+", NULL); @@ -730,7 +745,7 @@ out: static void listenloop(struct muth *muth, va_list args) { vavar(int, lfd); - int fd; + int fd, sfd; struct hthead *req; while(1) { @@ -740,7 +755,12 @@ static void listenloop(struct muth *muth, va_list args) flog(LOG_ERR, "recvreq: %s", strerror(errno)); break; } - mustart(serve, req, fd); + if((sfd = reconn()) < 0) { + close(fd); + freehthead(req); + continue; + } + mustart(serve, req, fd, sfd); } } diff --git a/src/callscgi.c b/src/callscgi.c index ee46ac1..ef31c4c 100644 --- a/src/callscgi.c +++ b/src/callscgi.c @@ -233,14 +233,30 @@ static void startnolisten(void) static int sconnect(void) { int fd; + int err; + socklen_t errlen; fd = socket(cafamily, SOCK_STREAM, 0); - if(connect(fd, curaddr, caddrlen)) { + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + while(1) { + if(!connect(fd, curaddr, caddrlen)) + return(fd); + if(errno == EAGAIN) { + block(-1, 0, 1); + continue; + } + if(errno == EINPROGRESS) { + block(fd, EV_WRITE, 30); + errlen = sizeof(err); + if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) || ((errno = err) != 0)) { + close(fd); + return(-1); + } + return(fd); + } close(fd); return(-1); } - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); - return(fd); } static int econnect(void) @@ -507,7 +523,6 @@ static void serve(struct muth *muth, va_list args) struct charbuf head; struct hthead *resp; - sfd = reconn(); is = mtstdopen(fd, 1, 60, "r+", NULL); os = mtstdopen(sfd, 1, 600, "r+", NULL); @@ -537,7 +552,7 @@ out: static void listenloop(struct muth *muth, va_list args) { vavar(int, lfd); - int fd; + int fd, sfd; struct hthead *req; while(1) { @@ -547,7 +562,12 @@ static void listenloop(struct muth *muth, va_list args) flog(LOG_ERR, "recvreq: %s", strerror(errno)); break; } - mustart(serve, req, fd); + if((sfd = reconn()) < 0) { + close(fd); + freehthead(req); + continue; + } + mustart(serve, req, fd, sfd); } } -- 2.20.1