d282b1c0b5eb16ba843ff970eb36172594c5d6b0
hiram
  Wed Jun 1 10:57:16 2011 -0700
implement cgiApoptosis system
diff --git src/hg/lib/web.c src/hg/lib/web.c
index f60b50d..a9c381f 100644
--- src/hg/lib/web.c
+++ src/hg/lib/web.c
@@ -1107,97 +1107,113 @@
 if ((retDb == NULL) || !hDbExists(retDb))
     {
     retDb = hDefaultDb();
     }
 
 /* If genomes don't match, then get the default db for that genome */
 if (differentWord(genome, hGenome(retDb)))
     {
     retDb = hDefaultDbForGenome(genome);
     }
 
 return retDb;
 }
 
 /* phoneHome business */
-static void alarmExit(int status)
-/* signal handler for SIGALRM for phoneHome function */
+static void cgiApoptosis(int status)
+/* signal handler for SIGALRM for phoneHome function and CGI expiration */
 {
 exit(0);
 }
 
 static void phoneHome()
 {
 static boolean beenHere = FALSE;
 if (beenHere)  /* one at a time please */
     return;
 beenHere = TRUE;
 
+char *expireTime = cfgOptionDefault("browser.cgiExpireMinutes", "20");
+unsigned expireMinutes = sqlUnsigned(expireTime);
+unsigned long expireSeconds = expireMinutes * 60;
+
 char trashFile[PATH_LEN];
 safef(trashFile, sizeof(trashFile), "%s/registration.txt", trashDir());
+
+/* trashFile does not exist during command line execution */
 if(fileExists(trashFile))	/* update access time for trashFile */
     {
     struct utimbuf ut;
     struct stat mystat;
     ZeroVar(&mystat);
     if (stat(trashFile,&mystat)==0)
 	{
 	ut.actime = clock1();
 	ut.modtime = mystat.st_mtime;
 	}
     else
 	{
 	ut.actime = ut.modtime = clock1();
 	}
     (void) utime(trashFile, &ut);
+    if (expireSeconds > 0)
+	{
+	(void) signal(SIGALRM, cgiApoptosis);
+	(void) alarm(expireSeconds);	/* CGI timeout */
+	}
     return;
     }
 
 char *scriptName = cgiScriptName();
 char *ip = getenv("SERVER_ADDR");
 if (scriptName && ip)  /* will not be true from command line execution */
     {
     FILE *f = fopen(trashFile, "w");
     if (f)		/* rigamarole only if we can get a trash file */
 	{
 	time_t now = time(NULL);
 	char *localTime;
 	extern char *tzname[2];
 	struct tm *tm = localtime(&now);
 	localTime = sqlUnixTimeToDate(&now,FALSE); /* FALSE == localtime */
 	fprintf(f, "%s, %s, %s %s, %s\n", scriptName, ip, localTime,
 	    tm->tm_isdst ? tzname[1] : tzname[0], trashFile);
 	fclose(f);
 	chmod(trashFile, 0666);
 	pid_t pid0 = fork();
 	if (0 == pid0)	/* in child */
 	    {
 	    close(STDOUT_FILENO); /* do not hang up Apache finish for parent */
-	    (void) signal(SIGALRM, alarmExit);
+	    (void) signal(SIGALRM, cgiApoptosis);
 	    (void) alarm(6);	/* timeout here in 6 seconds */
 #include "versionInfo.h"
 	    char url[1024];
 	    safef(url, sizeof(url), "%s%s",
 	"http://genomewiki.ucsc.edu/cgi-bin/useCount?version=browser.v",
 		CGI_VERSION);
 
 	    /* 6 second alarm will exit this page fetch if it does not work */
 	    (void) htmlPageGetWithCookies(url, NULL); /* ignore return */
 
 	    exit(0);
 	    }	/* child of fork has done exit(0) normally or via alarm */
 	}		/* trash file open OK */
+    if (expireSeconds > 0)
+	{
+	(void) signal(SIGALRM, cgiApoptosis);
+	(void) alarm(expireSeconds);	/* CGI timeout */
+	}
     }			/* an actual CGI binary */
 }			/* phoneHome()	*/
 /* phoneHome business */
 
 void getDbGenomeClade(struct cart *cart, char **retDb, char **retGenome,
 		      char **retClade, struct hash *oldVars)
 /* Examine CGI and cart variables to determine which db, genome, or clade
  *  has been selected, and then adjust as necessary so that all three are
  * consistent.  Detect changes and reset db-specific cart variables.
  * Save db, genome and clade in the cart so it will be consistent hereafter.
  * The order of preference here is as follows:
  * If we got a request that explicitly names the db, that takes
  * highest priority, and we synch the organism to that db.
  * If we get a cgi request for a specific organism then we use that
  * organism to choose the DB.  If just clade, go from there.