You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Dean Gaudet <dg...@arctic.org> on 1997/09/27 21:21:37 UTC

[PATCH] PR#523: properly close all standard descriptors

When detaching we really need to close out all the standard descriptors. 
stdin/out should be replaced with /dev/null and stderr should be wired
into the error_log.  If we don't do this then it becomes problematic
restarting the server via crontab (the cron subjob which mails the output
to the owner will have to hang around for the entire life of the server),
or via rsh (the rsh will hang around for the entire life of the server). 

The typical workaround for these problems at the moment is to manually
send everything to /dev/null.  But if you do this then you miss the config
file diagnostics, and in order to get them you have to re-run without the
/dev/null redirections.  This can't be easily automated, so crontab and
rsh restarts never give you diagnostics. 

This patch reopens stdin/out during detach().  It leaves stderr alone
until open_logs, where it directs the output to the error_log (or
/dev/null if there was a problem opening the error_log).  If /dev/null
isn't around this thing still continues ... but with the original
stdin/out (and possibly err). 

This is borderline feature.

Dean

Index: main/http_log.c
===================================================================
RCS file: /export/home/cvs/apachen/src/main/http_log.c,v
retrieving revision 1.34
diff -u -r1.34 http_log.c
--- http_log.c	1997/09/12 20:37:33	1.34
+++ http_log.c	1997/09/27 19:19:06
@@ -224,8 +224,35 @@
 void open_logs (server_rec *s_main, pool *p)
 {
     server_rec *virt, *q;
+#ifndef WIN32
+    int replace_stderr;
+#endif
 
     open_error_log (s_main, p);
+
+#ifndef WIN32
+    replace_stderr = 1;
+    if (s_main->error_log) {
+	/* replace stderr with this new log */
+	fflush(stderr);
+	if (dup2(fileno(s_main->error_log), 2) == -1) {
+	    aplog_error(APLOG_MARK, APLOG_CRIT, s_main,
+		"unable to replace stderr with error_log: %s",
+		strerror(errno));
+	} else {
+	    replace_stderr = 0;
+	}
+    }
+    /* note that stderr may still need to be replaced with something
+     * because it points to the old error log, or back to the tty
+     * of the submitter.
+     */
+    if (replace_stderr && freopen("/dev/null", "w", stderr) == NULL) {
+	aplog_error(APLOG_MARK, APLOG_CRIT, s_main,
+	    "unable to replace stderr with /dev/null: %s",
+	    strerror(errno));
+    }
+#endif
 
     for (virt = s_main->next; virt; virt = virt->next) {
 	if (virt->error_fname)
Index: main/http_main.c
===================================================================
RCS file: /export/home/cvs/apachen/src/main/http_main.c,v
retrieving revision 1.226
diff -u -r1.226 http_main.c
--- http_main.c	1997/09/25 01:03:22	1.226
+++ http_main.c	1997/09/27 19:19:07
@@ -2077,6 +2077,25 @@
 	exit(1);
     }
 #endif
+
+    /* close out the standard file descriptors */
+    if (freopen("/dev/null", "r", stdin) == NULL) {
+	fprintf(stderr, "httpd: unable to replace stdin with /dev/null: %s\n",
+		strerror(errno));
+	/* continue anyhow -- note we can't close out descriptor 0 because we
+	 * have nothing to replace it with, and if we didn't have a descriptor
+	 * 0 the next file would be created with that value ... leading to
+	 * havoc.
+	 */
+    }
+    if (freopen("/dev/null", "w", stdout) == NULL) {
+	fprintf(stderr, "httpd: unable to replace stdout with /dev/null: %s\n",
+		strerror(errno));
+    }
+    /* stderr is a tricky one, we really want it to be the error_log,
+     * but we haven't opened that yet.  So leave it alone for now and it'll
+     * be reopened moments later.
+     */
 #endif /* ndef WIN32 */
 }