From 7282f33961573223e8438b5a1649ca331cc3cf57 Mon Sep 17 00:00:00 2001 From: Grzegorz Nosek Date: Sat, 28 Feb 2009 12:35:29 +0100 Subject: Simple prefork support (start as fcgiwrap -c , with a suitable socket on FD 0) --- fcgiwrap.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) (limited to 'fcgiwrap.c') diff --git a/fcgiwrap.c b/fcgiwrap.c index fee22b2..2d925ef 100644 --- a/fcgiwrap.c +++ b/fcgiwrap.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -12,6 +13,8 @@ #include #include #include +#include +#include extern char **environ; static char * const * inherited_environ; @@ -517,7 +520,7 @@ err_pipein: FCGI_puts("System error"); } -int main(/* int argc, char **argv */) +static void fcgiwrap_main(void) { signal(SIGCHLD, SIG_IGN); signal(SIGPIPE, SIG_IGN); @@ -527,7 +530,83 @@ int main(/* int argc, char **argv */) while (FCGI_Accept() >= 0) { handle_fcgi_request(); } +} - return 0; +static volatile sig_atomic_t nrunning; + +static void sigchld_handler(int dummy) +{ + int status; + + while ((dummy = waitpid(-1, &status, WNOHANG)) != -1) { + /* sanity check */ + if (nrunning > 0) + nrunning--; + + /* we _should_ print something about the exit code + * but the sighandler context is _very_ bad for this + */ + } +} + +static void prefork(int nchildren) +{ + int startup = 1; + + if (nchildren == 1) { + return; + } + + signal(SIGCHLD, sigchld_handler); + + while (1) { + while (nrunning < nchildren) { + pid_t pid = fork(); + if (pid == 0) { + return; + } else if (pid != -1) { + nrunning++; + } else { + if (startup) { + fprintf(stderr, "Failed to prefork: %s\n", strerror(errno)); + exit(1); + } else { + fprintf(stderr, "Failed to fork: %s\n", strerror(errno)); + break; + } + } + } + startup = 0; + pause(); + } } +int main(int argc, char **argv) +{ + int nchildren = 1; + int c; + + while ((c = getopt(argc, argv, "c:")) != -1) { + switch (c) { + case 'c': + nchildren = atoi(optarg); + break; + case '?': + if (optopt == 'c') + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + else if (isprint(optopt)) + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + else + fprintf(stderr, + "Unknown option character `\\x%x'.\n", + optopt); + return 1; + default: + abort(); + } + } + + prefork(nchildren); + fcgiwrap_main(); + return 0; +} -- cgit v1.2.3