Arrange for output from Perl's "warn" to go to the mainlog by default.
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Thu, 27 Jan 2005 15:00:38 +0000 (15:00 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Thu, 27 Jan 2005 15:00:38 +0000 (15:00 +0000)
doc/doc-src/spec.src
doc/doc-txt/ChangeLog
src/src/daemon.c
src/src/perl.c

index 5ecbd9e9eef352d7cd0d019074bdb27de4f217d1..69ebca07deb03565ece8599542dcccee8ce5f770 100644 (file)
@@ -1,4 +1,4 @@
-. $Cambridge: exim/doc/doc-src/spec.src,v 1.5 2005/01/27 10:25:35 ph10 Exp $
+. $Cambridge: exim/doc/doc-src/spec.src,v 1.6 2005/01/27 15:00:38 ph10 Exp $
 .
 .set version "4.50"
 .set previousversion "4.40"
@@ -10673,21 +10673,29 @@ terminating newline.
 
 .em
 .section Use of standard output and error by Perl
+.index Perl||standard output and error
 You should not write to the standard error or output streams from within your 
-Perl code, as it is not defined how these are set up. In versions of Exim up to 
-at least 4.50, it is possible for the standard output or error to refer to the 
-SMTP connection during message reception. Writing to this stream is likely to 
-cause chaos. Something may be done about this in later releases.
-
-Unfortunately, the Perl \warn\ statment writes to the standard error stream, 
-and this may be embedded in Perl modules that you use, but over which you have 
-no control. One way round this is to ensure that the following Perl magic is 
-obeyed before \warn\ is used:
-.display asis
-$SIG{__WARN__} = sub { Exim::log_write($_[0]) };
-.endd
-This causes the output of the \warn\ statement to be written to Exim's log 
-file.
+Perl code, as it is not defined how these are set up. In versions of Exim  
+before 4.50, it is possible for the standard output or error to refer to the 
+SMTP connection during message reception via the daemon. Writing to this stream
+is certain to cause chaos. From Exim 4.50 onwards, the standard output and
+error streams are connected to \(/dev/null)\ in the daemon. The chaos is 
+avoided, but the output is lost.
+
+.index Perl||\warn\, use of
+The Perl \warn\ statement writes to the standard error stream by default. Calls 
+to \warn\ may be embedded in Perl modules that you use, but over which you have
+no control. When Exim starts up the Perl interpreter, it arranges for output
+from the \warn\ statement to be written to the Exim main log. You can change 
+this by including appropriate Perl magic somewhere in your Perl code. For 
+example, to discard \warn\ output completely, you need this:
+.display asis
+$SIG{__WARN__} = sub { };
+.endd
+Whenever a \warn\ is obeyed, the anonymous subroutine is called. In this 
+example, the code for the subroutine is empty, so it does nothing, but you can
+include any Perl code that you like. The text of the \warn\ message is passed
+as the first subroutine argument.
 .nem
 
 
index 799999e70e52643c8c353f77db8bbfeef6db1120..eaec31c78f83253c7eedac00f304885797c1c364 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.75 2005/01/27 10:26:14 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.76 2005/01/27 15:00:39 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -351,6 +351,16 @@ Exim version 4.50
 
       verify = header_sender/callout=defer_ok
 
+75. A backgrounded daemon closed stdin/stdout/stderr on entry; this meant that
+    those file descriptors could be used for SMTP connections. If anything
+    wrote to stderr (the example that came up was "warn" in embedded Perl), it
+    could be sent to the SMTP client, causing chaos. The daemon now opens
+    stdin, stdout, and stderr to /dev/null when it puts itself into the
+    background.
+
+76. Arrange for output from Perl's "warn" command to be written to Exim's main
+    log by default. The user can override this with suitable Perl magic.
+
 
 ----------------------------------------------------
 See the note above about the 4.44 and 4.50 releases.
index 1c274d732008b0cda04087211aefb8bd098946eb..88dd69d21c02318d3d00db631fbddf1576e65a0b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/daemon.c,v 1.5 2005/01/04 10:37:55 ph10 Exp $ */
+/* $Cambridge: exim/src/src/daemon.c,v 1.6 2005/01/27 15:00:39 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1124,26 +1124,35 @@ if (daemon_listen)
     }
   }
 
-/* We now close all open file descriptors that we know about, and disconnect
-from the controlling terminal, unless background_daemon is unset. This is
-always unset when debugging, but can also be forced. Most modern Unixes seem to
-have setsid() for getting rid of the controlling terminal. For any OS that
-doesn't, setsid() can be #defined as a no-op, or as something else. */
+/* The variable background_daemon is always false when debugging, but
+can also be forced false in order to keep a non-debugging daemon in the
+foreground. If background_daemon is true, close all open file descriptors that
+we know about, but then re-open stdin, stdout, and stderr to /dev/null.
+
+This is protection against any called functions (in libraries, or in
+Perl, or whatever) that think they can write to stderr (or stdout). Before this
+was added, it was quite likely that an SMTP connection would use one of these
+file descriptors, in which case writing random stuff to it caused chaos.
+
+Then disconnect from the controlling terminal, Most modern Unixes seem to have
+setsid() for getting rid of the controlling terminal. For any OS that doesn't,
+setsid() can be #defined as a no-op, or as something else. */
 
 if (background_daemon)
   {
-  log_close_all();  /* Just in case anything was logged earlier */
-  search_tidyup();  /* Just in case any were used in reading the config. */
-  close(0);         /* Get rid of stdin/stdout/stderr */
+  log_close_all();    /* Just in case anything was logged earlier */
+  search_tidyup();    /* Just in case any were used in reading the config. */
+  close(0);           /* Get rid of stdin/stdout/stderr */
   close(1);
   close(2);
+  exim_nullstd();     /* Connect stdin/stdout/stderr to /dev/null */ 
   log_stderr = NULL;  /* So no attempt to copy paniclog output */
 
   /* If the parent process of this one has pid == 1, we are re-initializing the
-  daemon as the result of a SIGHUP. In this case, there is no need to do any
-  forking, because the controlling terminal has long gone. Otherwise, fork,
-  in case current process is a process group leader (see 'man setsid' for an
-  explanation). */
+  daemon as the result of a SIGHUP. In this case, there is no need to do 
+  anything, because the controlling terminal has long gone. Otherwise, fork, in
+  case current process is a process group leader (see 'man setsid' for an
+  explanation) before calling setsid(). */
 
   if (getppid() != 1)
     {
index a22fe6f401ff98d86189c0d88f614f4da92f93b8..5bb7ad3608fd0dd7c312910ffbbe7a6520f35dee 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/perl.c,v 1.2 2004/12/20 11:46:21 ph10 Exp $ */
+/* $Cambridge: exim/src/src/perl.c,v 1.3 2005/01/27 15:00:39 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -109,6 +109,21 @@ init_perl(uschar *startup_code)
   perl_run(interp_perl);
     {
     dSP;
+
+    /*********************************************************************/
+    /* These lines by PH added to make "warn" output go to the Exim log; I
+    hope this doesn't break anything. */
+     
+    sv = newSVpv(
+      "$SIG{__WARN__} = sub { my($s) = $_[0];"
+      "$s =~ s/\\n$//;" 
+      "Exim::log_write($s) };", 0);
+    PUSHMARK(SP);
+    perl_eval_sv(sv, G_SCALAR|G_DISCARD|G_KEEPERR);
+    SvREFCNT_dec(sv);
+    if (SvTRUE(ERRSV)) return US SvPV(ERRSV, len);
+    /*********************************************************************/
     sv = newSVpv(CS startup_code, 0);
     PUSHMARK(SP);
     perl_eval_sv(sv, G_SCALAR|G_DISCARD|G_KEEPERR);