On further testing, PQping also needs an explicit check for AUTH_REQ.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 27 Nov 2010 07:11:45 +0000 (02:11 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 27 Nov 2010 07:11:45 +0000 (02:11 -0500)
The pg_fe_sendauth code might fail if it can't handle the authentication
request message type --- if so, ping should still say the server is up.

src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/libpq-int.h

index bff9b478f6602a6440646231a22a5102d8040d5c..b1523a6a893422af5df9bd25abbe6da9d554aa42 100644 (file)
@@ -2321,6 +2321,8 @@ keep_going:                       /* We will come back to here until there is
                }
 
                /* It is an authentication request. */
+               conn->auth_req_received = true;
+
                /* Get the type of request. */
                if (pqGetInt((int *) &areq, 4, conn))
                {
@@ -2589,11 +2591,18 @@ internal_ping(PGconn *conn)
        return PQPING_OK;
 
    /*
-    * Here is the interesting part of "ping": determine the cause of the
+    * Here begins the interesting part of "ping": determine the cause of the
     * failure in sufficient detail to decide what to return.  We do not want
     * to report that the server is not up just because we didn't have a valid
-    * password, for example.
-    *
+    * password, for example.  In fact, any sort of authentication request
+    * implies the server is up.  (We need this check since the libpq side
+    * of things might have pulled the plug on the connection before getting
+    * an error as such from the postmaster.)
+    */
+   if (conn->auth_req_received)
+       return PQPING_OK;
+
+   /*
     * If we failed to get any ERROR response from the postmaster, report
     * PQPING_NO_RESPONSE.  This result could be somewhat misleading for a
     * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
@@ -2672,6 +2681,7 @@ makeEmptyPGconn(void)
    conn->std_strings = false;  /* unless server says differently */
    conn->verbosity = PQERRORS_DEFAULT;
    conn->sock = -1;
+   conn->auth_req_received = false;
    conn->password_needed = false;
    conn->dot_pgpass_used = false;
 #ifdef USE_SSL
index f6a7f39065a74b090a8bbd03de3fc8e8473fa8a0..ce5f330f9ea47a69fc5cb611aa30ddf518b243f3 100644 (file)
@@ -349,6 +349,7 @@ struct pg_conn
    SockAddr    raddr;          /* Remote address */
    ProtocolVersion pversion;   /* FE/BE protocol version in use */
    int         sversion;       /* server version, e.g. 70401 for 7.4.1 */
+   bool        auth_req_received;  /* true if any type of auth req received */
    bool        password_needed;    /* true if server demanded a password */
    bool        dot_pgpass_used;    /* true if used .pgpass */
    bool        sigpipe_so;     /* have we masked SIGPIPE via SO_NOSIGPIPE? */