]> granicus.if.org Git - postgresql/commitdiff
Try to make silent_mode behave somewhat reasonably.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 24 Aug 2009 20:08:40 +0000 (20:08 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 24 Aug 2009 20:08:40 +0000 (20:08 +0000)
Instead of sending stdout/stderr to /dev/null after forking away from the
terminal, send them to postmaster.log within the data directory.  Since
this opens the door to indefinite logfile bloat, recommend even more
strongly that log output be redirected when using silent_mode.

Move the postmaster's initial calls of load_hba() and load_ident() down
to after we have started the log collector, if we are going to.  This
is so that errors reported by them will appear in the "usual" place.

Reclassify silent_mode as a LOGGING_WHERE, not LOGGING_WHEN, parameter,
since it's got absolutely nothing to do with the latter category.

In passing, fix some obsolete references to -S ... this option hasn't
had that switch letter for a long time.

Back-patch to 8.4, since as of 8.4 load_hba() and load_ident() are more
picky (and thus more likely to fail) than they used to be.  This entire
change was driven by a complaint about those errors disappearing into
the bit bucket.

doc/src/sgml/config.sgml
src/backend/postmaster/postmaster.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample

index dbdd0a0dbc46bf32000c46e9be8bd9a1703260a8..0864465f32aa40dda5b45445b19229482fa9727b 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.220 2009/06/17 21:58:48 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.220.2.1 2009/08/24 20:08:40 tgl Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -2572,7 +2572,37 @@ local0.*    /var/log/postgresql
         </para>
        </listitem>
       </varlistentry>
-      
+
+     <varlistentry id="guc-silent-mode" xreflabel="silent_mode">
+      <term><varname>silent_mode</varname> (<type>boolean</type>)</term>
+      <indexterm>
+       <primary><varname>silent_mode</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        Runs the server silently. If this parameter is set, the server
+        will automatically run in background and disassociate from the
+        controlling terminal.
+        This parameter can only be set at server start.
+       </para>
+
+       <caution>
+       <para>
+        When this parameter is set,
+        the server's standard output and standard error are redirected
+        to the file <filename>postmaster.log</> within the data directory.
+        There is no provision for rotating this file, so it will grow
+        indefinitely unless server log output is redirected elsewhere
+        by other settings.  It is recommended that <varname>log_destination</>
+        be set to <literal>syslog</> or that <varname>logging_collector</> be
+        enabled when using this option.  Even with those measures, errors
+        reported early during startup may appear in
+        <filename>postmaster.log</> rather than the normal log destination.
+       </para>
+       </caution>
+      </listitem>
+     </varlistentry>
+
       </variablelist>
     </sect2>
      <sect2 id="runtime-config-logging-when">
@@ -2706,26 +2736,6 @@ local0.*    /var/log/postgresql
        </listitem>
       </varlistentry>
 
-     <varlistentry id="guc-silent-mode" xreflabel="silent_mode">
-      <term><varname>silent_mode</varname> (<type>boolean</type>)</term>
-      <indexterm>
-       <primary><varname>silent_mode</> configuration parameter</primary>
-      </indexterm>
-      <listitem>
-       <para>
-        Runs the server silently. If this parameter is set, the server
-        will automatically run in background and any controlling
-        terminals are disassociated.
-        The server's standard output and standard error are redirected
-        to <literal>/dev/null</>, so any messages sent to them will be lost.
-        Unless <application>syslog</> logging is selected or
-        <varname>logging_collector</> is enabled, using this parameter
-        is discouraged because it makes it impossible to see error messages.
-        This parameter can only be set at server start.
-       </para>
-      </listitem>
-     </varlistentry>
-
      </variablelist>
 
     <para>
index db109e9b1b6c843494fbf671bbfb235a7d355a22..ab9fb8725aad214d5cf7d6c4f2c46bddcb3f4f4d 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.583.2.5 2009/08/24 18:09:54 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.583.2.6 2009/08/24 20:08:40 tgl Exp $
  *
  * NOTES
  *
@@ -191,7 +191,7 @@ static int  SendStop = false;
 
 /* still more option variables */
 bool           EnableSSL = false;
-bool           SilentMode = false; /* silent mode (-S) */
+bool           SilentMode = false; /* silent_mode */
 
 int                    PreAuthDelay = 0;
 int                    AuthenticationTimeout = 60;
@@ -744,7 +744,7 @@ PostmasterMain(int argc, char *argv[])
        }
 
        /*
-        * Fork away from controlling terminal, if -S specified.
+        * Fork away from controlling terminal, if silent_mode specified.
         *
         * Must do this before we grab any interlock files, else the interlocks
         * will show the wrong PID.
@@ -894,20 +894,6 @@ PostmasterMain(int argc, char *argv[])
         */
        set_max_safe_fds();
 
-       /*
-        * Load configuration files for client authentication.
-        */
-       if (!load_hba())
-       {
-               /*
-                * It makes no sense continue if we fail to load the HBA file, since
-                * there is no way to connect to the database in this case.
-                */
-               ereport(FATAL,
-                               (errmsg("could not load pg_hba.conf")));
-       }
-       load_ident();
-
        /*
         * Initialize the list of active backends.
         */
@@ -1023,6 +1009,20 @@ PostmasterMain(int argc, char *argv[])
         */
        autovac_init();
 
+       /*
+        * Load configuration files for client authentication.
+        */
+       if (!load_hba())
+       {
+               /*
+                * It makes no sense to continue if we fail to load the HBA file,
+                * since there is no way to connect to the database in this case.
+                */
+               ereport(FATAL,
+                               (errmsg("could not load pg_hba.conf")));
+       }
+       load_ident();
+
        /*
         * Remember postmaster startup time
         */
@@ -1204,15 +1204,46 @@ reg_reply(DNSServiceRegistrationReplyErrorType errorCode, void *context)
 
 
 /*
- * Fork away from the controlling terminal (-S option)
+ * Fork away from the controlling terminal (silent_mode option)
+ *
+ * Since this requires disconnecting from stdin/stdout/stderr (in case they're
+ * linked to the terminal), we re-point stdin to /dev/null and stdout/stderr
+ * to "postmaster.log" in the data directory, where we're already chdir'd.
  */
 static void
 pmdaemonize(void)
 {
 #ifndef WIN32
-       int                     i;
+       const char *pmlogname = "postmaster.log";
+       int                     dvnull;
+       int                     pmlog;
        pid_t           pid;
+       int                     res;
+
+       /*
+        * Make sure we can open the files we're going to redirect to.  If this
+        * fails, we want to complain before disconnecting.  Mention the full path
+        * of the logfile in the error message, even though we address it by
+        * relative path.
+        */
+       dvnull = open(DEVNULL, O_RDONLY, 0);
+       if (dvnull < 0)
+       {
+               write_stderr("%s: could not open file \"%s\": %s\n",
+                                        progname, DEVNULL, strerror(errno));
+               ExitPostmaster(1);
+       }
+       pmlog = open(pmlogname, O_CREAT | O_WRONLY | O_APPEND, 0600);
+       if (pmlog < 0)
+       {
+               write_stderr("%s: could not open log file \"%s/%s\": %s\n",
+                                        progname, DataDir, pmlogname, strerror(errno));
+               ExitPostmaster(1);
+       }
 
+       /*
+        * Okay to fork.
+        */
        pid = fork_process();
        if (pid == (pid_t) -1)
        {
@@ -1231,8 +1262,8 @@ pmdaemonize(void)
        MyStartTime = time(NULL);
 
        /*
-        * GH: If there's no setsid(), we hopefully don't need silent mode. Until
-        * there's a better solution.
+        * Some systems use setsid() to dissociate from the TTY's process group,
+        * while on others it depends on stdin/stdout/stderr.  Do both if possible.
         */
 #ifdef HAVE_SETSID
        if (setsid() < 0)
@@ -1242,14 +1273,26 @@ pmdaemonize(void)
                ExitPostmaster(1);
        }
 #endif
-       i = open(DEVNULL, O_RDWR, 0);
-       dup2(i, 0);
-       dup2(i, 1);
-       dup2(i, 2);
-       close(i);
+
+       /*
+        * Reassociate stdin/stdout/stderr.  fork_process() cleared any pending
+        * output, so this should be safe.  The only plausible error is EINTR,
+        * which just means we should retry.
+        */
+       do {
+               res = dup2(dvnull, 0);
+       } while (res < 0 && errno == EINTR);
+       close(dvnull);
+       do {
+               res = dup2(pmlog, 1);
+       } while (res < 0 && errno == EINTR);
+       do {
+               res = dup2(pmlog, 2);
+       } while (res < 0 && errno == EINTR);
+       close(pmlog);
 #else                                                  /* WIN32 */
        /* not supported */
-       elog(FATAL, "SilentMode not supported under WIN32");
+       elog(FATAL, "silent_mode is not supported under Windows");
 #endif   /* WIN32 */
 }
 
@@ -3241,8 +3284,8 @@ BackendInitialize(Port *port)
        if (!load_hba())
        {
                /*
-                * It makes no sense continue if we fail to load the HBA file, since
-                * there is no way to connect to the database in this case.
+                * It makes no sense to continue if we fail to load the HBA file,
+                * since there is no way to connect to the database in this case.
                 */
                ereport(FATAL,
                                (errmsg("could not load pg_hba.conf")));
index 210bd6ba6a5bb452fa5a07931bd799716260ffd4..6b67f8692a06e1cd6d026cf75ac42004f8e8ab8d 100644 (file)
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.505 2009/06/11 14:49:06 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.505.2.1 2009/08/24 20:08:40 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -727,7 +727,7 @@ static struct config_bool ConfigureNamesBool[] =
                true, NULL, NULL
        },
        {
-               {"silent_mode", PGC_POSTMASTER, LOGGING_WHEN,
+               {"silent_mode", PGC_POSTMASTER, LOGGING_WHERE,
                        gettext_noop("Runs the server silently."),
                        gettext_noop("If this parameter is set, the server will automatically run in the "
                                 "background and any controlling terminals are dissociated.")
index 3f7b43f0ccc54d0a966a886a575d4cc32cb61217..645f355b07e9b9cb8d2088a834bcd975a75c7e8f 100644 (file)
 #syslog_facility = 'LOCAL0'
 #syslog_ident = 'postgres'
 
+#silent_mode = off                     # Run server silently.
+                                       # DO NOT USE without syslog or
+                                       # logging_collector
+                                       # (change requires restart)
+
 
 # - When to Log -
 
                                        # statements running at least this number
                                        # of milliseconds
 
-#silent_mode = off                     # DO NOT USE without syslog or
-                                       # logging_collector
-                                       # (change requires restart)
 
 # - What to Log -