Move init_ps_display from postgres.c to postmaster.c, putting it
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 19 Oct 2001 00:44:08 +0000 (00:44 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 19 Oct 2001 00:44:08 +0000 (00:44 +0000)
just after receipt of the startup packet.  Now, postmaster children
that are waiting for client authentication response will show as
'postgres: user database host authentication'.  Also, do an
init_ps_display for startup/shutdown/checkpoint subprocesses,
so that they are readily identifiable as well.  Fix an obscure race
condition that could lead to Assert failure in the postmaster ---
attempting to start a checkpoint process before any connections have
been received led to calling PostmasterRandom before setting random_seed.

src/backend/postmaster/postmaster.c
src/backend/tcop/postgres.c

index 12cd5a164815066c64ed20d5bcb480bdb70ff313..8c5eb5ae9046989904ba8620f544a8c8980cc6e4 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.245 2001/10/03 21:58:28 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.246 2001/10/19 00:44:08 tgl Exp $
  *
  * NOTES
  *
@@ -73,7 +73,8 @@
 #include <fcntl.h>
 #include <time.h>
 #include <sys/param.h>
-/* moved here to prevent double define */
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #include <netdb.h>
 #include <limits.h>
 
 #include "utils/exc.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
+#include "utils/ps_status.h"
 #include "bootstrap/bootstrap.h"
 
 #include "pgstat.h"
@@ -194,6 +196,10 @@ int            PreAuthDelay = 0;
 int            AuthenticationTimeout = 60;
 int            CheckPointTimeout = 300;
 
+bool       HostnameLookup;     /* for ps display */
+bool       ShowPortNumber;
+bool       Log_connections = false;
+
 /* Startup/shutdown state */
 static pid_t StartupPID = 0,
            ShutdownPID = 0,
@@ -821,7 +827,7 @@ ServerLoop(void)
        struct timeval timeout_tv;
 
        if (CheckPointPID == 0 && checkpointed &&
-           Shutdown == NoShutdown && !FatalError)
+           Shutdown == NoShutdown && !FatalError && random_seed != 0)
        {
            time_t      now = time(NULL);
 
@@ -981,7 +987,9 @@ initMasks(fd_set *rmask, fd_set *wmask)
  * not return at all.
  *
  * (Note that elog(FATAL) stuff is sent to the client, so only use it
- * if that's what you want.)
+ * if that's what you want.  Return STATUS_ERROR if you don't want to
+ * send anything to the client, which would typically be appropriate
+ * if we detect a communications failure.)
  */
 static int
 ProcessStartupPacket(Port *port, bool SSLdone)
@@ -991,7 +999,12 @@ ProcessStartupPacket(Port *port, bool SSLdone)
    int32       len;
    void       *buf;
 
-   pq_getbytes((char *)&len, 4);
+   if (pq_getbytes((char *) &len, 4) == EOF)
+   {
+       elog(DEBUG, "incomplete startup packet");
+       return STATUS_ERROR;
+   }
+
    len = ntohl(len);
    len -= 4;
 
@@ -999,7 +1012,12 @@ ProcessStartupPacket(Port *port, bool SSLdone)
        elog(FATAL, "invalid length of startup packet");
 
    buf = palloc(len);
-   pq_getbytes(buf, len);
+
+   if (pq_getbytes(buf, len) == EOF)
+   {
+       elog(DEBUG, "incomplete startup packet");
+       return STATUS_ERROR;
+   }
 
    packet = buf;
 
@@ -1913,6 +1931,7 @@ split_opts(char **argv, int *argcp, char *s)
 static int
 DoBackend(Port *port)
 {
+   char       *remote_host;
    char       *av[ARGV_SIZE * 2];
    int         ac = 0;
    char        debugbuf[ARGV_SIZE];
@@ -1981,14 +2000,78 @@ DoBackend(Port *port)
 
    /*
     * Receive the startup packet (which might turn out to be a cancel
-    * request packet); then perform client authentication.
+    * request packet).
     */
    status = ProcessStartupPacket(port, false);
 
-   if (status == 127)
-       return 0;               /* cancel request processed */
+   if (status != STATUS_OK)
+       return 0;               /* cancel request processed, or error */
 
-   ClientAuthentication(MyProcPort); /* might not return, if failure */
+   /*
+    * Now that we have the user and database name, we can set the process
+    * title for ps.  It's good to do this as early as possible in startup.
+    *
+    * But first, we need the remote host name.
+    */
+   if (port->raddr.sa.sa_family == AF_INET)
+   {
+       unsigned short remote_port;
+       char       *host_addr;
+
+       remote_port = ntohs(port->raddr.in.sin_port);
+       host_addr = inet_ntoa(port->raddr.in.sin_addr);
+
+       remote_host = NULL;
+
+       if (HostnameLookup)
+       {
+           struct hostent *host_ent;
+
+           host_ent = gethostbyaddr((char *) &port->raddr.in.sin_addr,
+                                    sizeof(port->raddr.in.sin_addr),
+                                    AF_INET);
+
+           if (host_ent)
+           {
+               remote_host = palloc(strlen(host_addr) + strlen(host_ent->h_name) + 3);
+               sprintf(remote_host, "%s[%s]", host_ent->h_name, host_addr);
+           }
+       }
+
+       if (remote_host == NULL)
+           remote_host = pstrdup(host_addr);
+
+       if (ShowPortNumber)
+       {
+           char       *str = palloc(strlen(remote_host) + 7);
+
+           sprintf(str, "%s:%hu", remote_host, remote_port);
+           pfree(remote_host);
+           remote_host = str;
+       }
+   }
+   else
+   {
+       /* not AF_INET */
+       remote_host = "[local]";
+   }
+
+   /*
+    * Set process parameters for ps
+    *
+    * WARNING: On some platforms the environment will be moved around to
+    * make room for the ps display string. So any references to
+    * optarg or getenv() from above will be invalid after this call.
+    * Better use strdup or something similar.
+    */
+   init_ps_display(real_argc, real_argv, port->user, port->database,
+                   remote_host);
+   set_ps_display("authentication");
+
+   /*
+    * Now perform authentication exchange.
+    */
+   ClientAuthentication(port); /* might not return, if failure */
 
    /*
     * Done with authentication.  Disable timeout, and prevent SIGTERM/SIGQUIT
@@ -1998,6 +2081,10 @@ DoBackend(Port *port)
        elog(FATAL, "DoBackend: Unable to disable timer for auth timeout");
    PG_SETMASK(&BlockSig);
 
+   if (Log_connections)
+       elog(DEBUG, "connection: host=%s user=%s database=%s",
+            remote_host, port->user, port->database);
+
    /*
     * Don't want backend to be able to see the postmaster random number
     * generator state.  We have to clobber the static random_seed *and*
@@ -2138,7 +2225,7 @@ schedule_checkpoint(SIGNAL_ARGS)
 
    /* Ignore request if checkpointing is currently disabled */
    if (CheckPointPID == 0 && checkpointed &&
-       Shutdown == NoShutdown && !FatalError)
+       Shutdown == NoShutdown && !FatalError && random_seed != 0)
    {
        CheckPointPID = CheckPointDataBase();
        /* note: if fork fails, CheckPointPID stays 0; nothing happens */
@@ -2302,6 +2389,7 @@ SSDataBase(int xlop)
 
    if ((pid = fork()) == 0)    /* child */
    {
+       const char *statmsg;
        char       *av[ARGV_SIZE * 2];
        int         ac = 0;
        char        nbbuf[ARGV_SIZE];
@@ -2321,6 +2409,30 @@ SSDataBase(int xlop)
        /* Close the postmaster's sockets */
        ClosePostmasterPorts(true);
 
+       /*
+        * Identify myself via ps
+        *
+        * WARNING: On some platforms the environment will be moved around to
+        * make room for the ps display string.
+        */
+       switch (xlop)
+       {
+           case BS_XLOG_STARTUP:
+               statmsg = "startup subprocess";
+               break;
+           case BS_XLOG_CHECKPOINT:
+               statmsg = "checkpoint subprocess";
+               break;
+           case BS_XLOG_SHUTDOWN:
+               statmsg = "shutdown subprocess";
+               break;
+           default:
+               statmsg = "??? subprocess";
+               break;
+       }
+       init_ps_display(real_argc, real_argv, statmsg, "", "");
+       set_ps_display("");
+
        /* Set up command-line arguments for subprocess */
        av[ac++] = "postgres";
 
index 7fe5eae476215440d5ca948a669c9933c37dda14..bd51a57ab5433b49a6fc32705f95782b9808e63e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.234 2001/09/27 16:29:12 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.235 2001/10/19 00:44:08 tgl Exp $
  *
  * NOTES
  *   this is the "main" module of the postgres backend and
@@ -30,9 +30,6 @@
 #if HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
 #endif
@@ -77,14 +74,6 @@ extern char *optarg;
 
 char *debug_query_string;      /* used by pgmonitor */
 
-/*
- * for ps display
- */
-bool       HostnameLookup;
-bool       ShowPortNumber;
-
-bool       Log_connections = false;
-
 /* Note: whereToSendOutput is initialized for the bootstrap/standalone case */
 CommandDest whereToSendOutput = Debug;
 
@@ -1131,9 +1120,6 @@ PostgresMain(int argc, char *argv[],
    int         firstchar;
    StringInfo  parser_input;
 
-   char       *remote_host;
-   unsigned short remote_port;
-
    char       *potential_DataDir = NULL;
 
    /*
@@ -1165,6 +1151,8 @@ PostgresMain(int argc, char *argv[],
        MemoryContextInit();
    }
 
+   set_ps_display("startup");
+
    SetProcessingMode(InitProcessing);
 
    /*
@@ -1625,65 +1613,6 @@ PostgresMain(int argc, char *argv[],
        elog(FATAL, "%s: could not locate executable, bailing out...",
             real_argv[0]);
 
-   /*
-    * Find remote host name or address.
-    */
-   remote_host = NULL;
-
-   if (IsUnderPostmaster)
-   {
-       if (MyProcPort->raddr.sa.sa_family == AF_INET)
-       {
-           struct hostent *host_ent;
-           char       *host_addr;
-
-           remote_port = ntohs(MyProcPort->raddr.in.sin_port);
-           host_addr = inet_ntoa(MyProcPort->raddr.in.sin_addr);
-
-           if (HostnameLookup)
-           {
-               host_ent = gethostbyaddr((char *) &MyProcPort->raddr.in.sin_addr, sizeof(MyProcPort->raddr.in.sin_addr), AF_INET);
-
-               if (host_ent)
-               {
-                   remote_host = palloc(strlen(host_addr) + strlen(host_ent->h_name) + 3);
-                   sprintf(remote_host, "%s[%s]", host_ent->h_name, host_addr);
-               }
-           }
-
-           if (remote_host == NULL)
-               remote_host = pstrdup(host_addr);
-
-           if (ShowPortNumber)
-           {
-               char       *str = palloc(strlen(remote_host) + 7);
-
-               sprintf(str, "%s:%hu", remote_host, remote_port);
-               pfree(remote_host);
-               remote_host = str;
-           }
-       }
-       else
-/* not AF_INET */
-           remote_host = "[local]";
-
-
-       /*
-        * Set process parameters for ps
-        *
-        * WARNING: On some platforms the environment will be moved around to
-        * make room for the ps display string. So any references to
-        * optarg or getenv() from above will be invalid after this call.
-        * Better use strdup or something similar.
-        */
-       init_ps_display(real_argc, real_argv, username, DBName, remote_host);
-       set_ps_display("startup");
-   }
-
-   if (Log_connections)
-       elog(DEBUG, "connection: host=%s user=%s database=%s",
-            remote_host, username, DBName);
-
    /*
     * General initialization.
     *
@@ -1716,7 +1645,7 @@ PostgresMain(int argc, char *argv[],
    if (!IsUnderPostmaster)
    {
        puts("\nPOSTGRES backend interactive interface ");
-       puts("$Revision: 1.234 $ $Date: 2001/09/27 16:29:12 $\n");
+       puts("$Revision: 1.235 $ $Date: 2001/10/19 00:44:08 $\n");
    }
 
    /*