From 3f131e797d90d40147ba990af54770dd0058fc66 Mon Sep 17 00:00:00 2001 From: Bougyman Date: Tue, 3 May 2005 11:00:00 +0000 Subject: [PATCH] Allow spawn-fcgi in the foreground Been looking for a clean way to spawn fastcgi listeners in the foreground and I believe Trey has figured it out. This patch should take care of it by keeping spawn-fcgi from losing track of the copied listening processes and allow full supervison. taken from http://rubyists.com/articles/2005/05/03/spawn-fcgi-in-the-foreground --- README.supervise | 30 ++++++++++++++++++++++++++++++ cgi-fcgi/cgi-fcgi.c | 45 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 README.supervise diff --git a/README.supervise b/README.supervise new file mode 100644 index 0000000..a1dbea5 --- /dev/null +++ b/README.supervise @@ -0,0 +1,30 @@ +To use, call your cgi-fcgi -start -connect $host:$port script with +the -supervise option, like: + +cgi-fcgi -start -supervise -connect 127.0.0.1:1791 /path/to/dispatch.fcgi + +Full Supervise run script becomes + + #!/bin/sh + RAIL_NUMBER=$(basename $PWD|awk -F'-' '{print $2}') + RAILS_HOST=$( contains one line that is the full path to your rails root directory. +RAILS_ENV => contains one word, either ‘production’ or ‘development’ +RAILS_HOST => contains one IP address or FQDN + +You can set any other environment variables in this way by simply creating a +file with the variable name and its contents will become the value of that +environment variable. Because of the envdir ./env call before the cgi-fcgi +call, your rails application has access to any variables set in this way. diff --git a/cgi-fcgi/cgi-fcgi.c b/cgi-fcgi/cgi-fcgi.c index ef6e71e..dd5146c 100644 --- a/cgi-fcgi/cgi-fcgi.c +++ b/cgi-fcgi/cgi-fcgi.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "fcgi_config.h" @@ -582,7 +584,7 @@ static void FCGIUtil_BuildNameValueHeader( #define MAXARGS 16 static int ParseArgs(int argc, char *argv[], int *doBindPtr, int *doStartPtr, - char *connectPathPtr, char *appPathPtr, int *nServersPtr) { + char *connectPathPtr, char *appPathPtr, int *nServersPtr, int *doDaemonPtr) { int i, x, err = 0, @@ -598,6 +600,7 @@ static int ParseArgs(int argc, char *argv[], *connectPathPtr = '\0'; *appPathPtr = '\0'; *nServersPtr = 0; + *doDaemonPtr = TRUE; for(i = 0; i < MAXARGS; i++) av[i] = NULL; @@ -649,7 +652,7 @@ static int ParseArgs(int argc, char *argv[], } fclose(fp); err = ParseArgs(ac, av, doBindPtr, doStartPtr, - connectPathPtr, appPathPtr, nServersPtr); + connectPathPtr, appPathPtr, nServersPtr, doDaemonPtr); for(x = 1; x < ac; x++) { ASSERT(av[x] != NULL); free(av[x]); @@ -679,6 +682,8 @@ static int ParseArgs(int argc, char *argv[], MAXPATHLEN, argv[i]); err++; } + } else if(!strcmp(argv[i], "-supervise")) { + *doDaemonPtr = FALSE; } else { fprintf(stderr, "Unknown option %s\n", argv[i]); err++; @@ -732,7 +737,16 @@ static int ParseArgs(int argc, char *argv[], } return err; } - + +void handle_shutdown(int s) +{ + /* Kill our children processes */ + signal(s, SIG_IGN); + kill(0, s); + + exit(0); +} + int main(int argc, char **argv) { char **envp = environ; @@ -742,20 +756,22 @@ int main(int argc, char **argv) int headerLen, valueLen; char *equalPtr; FCGI_BeginRequestRecord beginRecord; - int doBind, doStart, nServers; + int doBind, doStart, nServers, doDaemon; char appPath[MAXPATHLEN], bindPath[MAXPATHLEN]; + int pid; if(ParseArgs(argc, argv, &doBind, &doStart, - (char *) &bindPath, (char *) &appPath, &nServers)) { + (char *) &bindPath, (char *) &appPath, &nServers, &doDaemon)) { fprintf(stderr, "Usage:\n" " cgi-fcgi -f , or\n" " cgi-fcgi -connect [] , or\n" -" cgi-fcgi -start -connect [] , or\n" +" cgi-fcgi -start -connect [-supervise] [] , or\n" " cgi-fcgi -bind -connect ,\n" "where is either the pathname of a UNIX domain socket\n" "or (if -bind is given) a hostName:portNumber specification\n" -"or (if -start is given) a :portNumber specification (uses local host).\n"); +"or (if -start is given) a :portNumber specification (uses local host).\n" +"-supervise is for running with runit or daemontools.\n"); exit(1); } @@ -771,12 +787,27 @@ int main(int argc, char **argv) bytesToRead = 0; } + /* Become a process group leader */ + setsid(); + + /* Register our signal handler */ + signal(SIGHUP, handle_shutdown); + signal(SIGINT, handle_shutdown); + signal(SIGTERM, handle_shutdown); + if(doBind) { appServerSock = OS_FcgiConnect(bindPath); } if(doStart && (!doBind || appServerSock < 0)) { FCGI_Start(bindPath, appPath, nServers); if(!doBind) { + if(!doDaemon) { + for(pid=nServers; pid != 0; pid--) { + wait(0); + } + } + signal(SIGTERM, SIG_IGN); + kill(0, SIGTERM); exit(0); } else { appServerSock = OS_FcgiConnect(bindPath);