From: Ian Jackson Date: Thu, 24 Mar 2016 22:03:16 +0000 (+0000) Subject: cgi-fcgi-interp: new garbage collection approach, wip implementation X-Git-Tag: archive/debian/5.0.0~58 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-utils.git;a=commitdiff_plain;h=2401434ef9f2a0bff941d7c0a6299b831c471dd2 cgi-fcgi-interp: new garbage collection approach, wip implementation --- diff --git a/cprogs/cgi-fcgi-interp.c b/cprogs/cgi-fcgi-interp.c index 602ffa6..4ae61d7 100644 --- a/cprogs/cgi-fcgi-interp.c +++ b/cprogs/cgi-fcgi-interp.c @@ -131,10 +131,12 @@ #include #include #include +#include #include +#include #include #include - + #include #include "myopt.h" @@ -145,7 +147,8 @@ #define MINHEXHASH 33 static const char *interp, *ident; -static int numservers, debugmode; +static int numservers=4, debugmode, stage2; +static int check_interval=300; void diee(const char *m) { err(127, "error: %s failed", m); @@ -179,6 +182,8 @@ static const struct cmdinfo cmdinfos[]= { { 0, 'g', 1, .sassignto= &ident }, { 0, 'M', 1, .call=of_iassign, .iassignto= &numservers }, { 0, 'D', 0, .iassignto= &debugmode, .arg= 1 }, + { 0, 'c', 1, .call=of_iassign, .iassignto= &check_interval }, + { "--stage2",0, 0, .iassignto= &stage2, .arg= 1 }, { 0 } }; @@ -366,63 +371,32 @@ static bool check_garbage(void) { return 0; } -static void tidy_1_garbage(const char *leaf) { +static void tidy_garbage(void) { + /* We lock l and re-check. The effect of this is that each + * stale socket is removed only once. So unless multiple updates to + * the script happen rapidly, we can't be racing with the cgi-fcgi + * (which is recreating the socket */ + int lockfd = -1; int r; - struct sockaddr_un sun; - - int fd = -1; - memset(&sun,0,sizeof(sun)); - sun.sun_family = AF_UNIX; - r = snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", run_base, leaf); - if (r >= sizeof(sun_path)) - goto cannot; + const char *lock_path = m_asprintf("%s/l%s",run_base,ident); - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd<0) err("create socket for tidying garbage"); + lockfd = open(lock_path, O_CREAT|O_RDWR, 0600); + if (lockfd<0) err(127,"create lock (%s)", lock_path); - r = fcntl(fd, F_SETFL, O_NONBLOCK); - if (r<0) err("set garbage socket nonblocking"); + r = flock(lockfd, LOCK_EX); + if (r) err(127,"lock lock (%s)", lock_path); - r = connect(fd, &sun, sizeof(sun)); - if (r) { - if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) - goto cannot; - if (errno != EINPROGRESS) - err("connect to garbage socket (%s)", sun.sun_path); - /* well, EINPROGRESS, let's just carry on and hope write works */ - } - - r = write( - - -static void tidy_garbage(void) { - const char *this_garbage = - m_asprintf("%s/g%lu.%lu", run_base, - (unsigned long)sock_stab.st_ino, - (unsigned long)getpid()); - - r = rename(socket_path, this_garbage); - if (r) { - if (!(errno == ENOENT)) - err("rename socket from old runner (from %s to %s)", - socket_path, this_garbage); - } - - DIR *d = opendir(run_base); - if (!d) err("open run directory (%d) to clean up garbage", run_base); - struct dirent *de; - while ((errno = 0, de = readdir(d))) { - if (de->d_name[0] != 'g') - continue; - tidy_1_garbage(de->d_name); + if (check_garbage()) { + r = unlink(socket_path); + if (r) { + if (!(errno == ENOENT)) + err(127,"remove out-of-date socket (%s)", socket_path); + } } - if (errno) err("read run directory (%d) to clean up garbage", run_base); - /* - (void)r; - if (r) { - printf("this_garb: %s\n", this_garbage); + r = close(lockfd); + if (r) errx(127,"close lock (%s)", lock_path); } static void shbang_opts(const char *const **argv_io, @@ -475,17 +449,17 @@ int main(int argc, const char *const *argv) { find_socket_path(); - bool havegarbage = check_garbage(); + bool isgarbage = check_garbage(); if (debugmode) { printf("socket: %s\n",socket_path); printf("interp: %s\n",interp); printf("script: %s\n",script); - printf("garbage: %d\n",havegarbage); + printf("garbage: %d\n",isgarbage); exit(0); } - if (havegarbage) + if (isgarbage) tidy_garbage(); exit(0);