On Friday October 10 2003 4:46, Ed L. wrote:
> I have libpq client program that repeatedly connects to a DB, queries,
> and then disconnects.  After a seemingly random number of such successful
> sessions (sometimes 30, sometimes hundreds), the backend mysteriously
> exits after the client calls PQsetdbLogin(), and the client hangs.  Any
> clues? Details below...
>
> Client:  C program linked with 7.2.1 libpq on HP-UX B.11.00 E 9000/803.
> Server:  PostgreSQL 7.3.2 on i686-pc-linux-gnu, compiled by GCC 2.96.

Still looking for clues as to the cause of this repeatable connection 
failure.  Passing an explicit connection timeout to PQconnectdb() escapes 
from any long hangs, but the hanging is still an issue I'd like to 
understand.  Attached is a small C program that reliably reproduces this 
problem on the setup above.  I added an explicit timeout to PQconnectdb() 
to wait only 30 seconds.  I'm curious to know if anyone can easily repeat 
the problem (careful, it will generate a bit of traffic, cpu load, and run 
forever).  My last example run showed 17 timeouts seemingly randomly 
dispersed among 5000 consecutive connection attempts.  

The server has plenty of available memory on a dual processor machine 
running Linux 2.4.18-3smp.  Tried to catch snapshot data from netstat on 
Recv-Q and Send-Q sizes on the server during a hang... that's a little iffy 
with the timing of grepping netstat output, but seems like the server's 
Recv-Q's were always zero and the Send-Q's were occasional in the tens 
(bytes?).

TIA for any help.
/*
 * test program to demonstrate connection hangs
 */
#include <stdio.h>
#include "libpq-fe.h"

static int tries = 0;
static int successes = 0;

void logmsg(const char *msg) {
    char timestamp[256];
    time_t t;
    
    t = time(NULL);
    strcpy(timestamp, asctime(localtime(&t)));
    timestamp[strlen(timestamp)-1] = '\0';
    fprintf(stderr,"%s [%d]  %s\n", timestamp, getpid(), msg);
    fflush(stderr);
}

const char* get_dbhname(PGconn *conn, char *dbhname)
{
    sprintf(dbhname, "[EMAIL PROTECTED]:%s:%s:%d", 
        PQuser(conn), PQhost(conn), PQport(conn), 
        PQdb(conn), PQbackendPID(conn));
    return dbhname;
}

main()
{
    char        msg[1024];
    char        dbhname[1024];

    PGconn     *conn;
    PGresult   *res;

    if ( ! (getenv("PGPORT") && getenv("PGHOST") &&
            getenv("PGUSER") && getenv("PGDATABASE") ) ) {
        logmsg("Please export PGPORT, PGUSER, PGHOST, and PGDATABASE for me.");
        exit(-1);
    }

    sprintf(dbhname, "[EMAIL PROTECTED]:%s:db=%s",
            getenv("PGUSER"), getenv("PGHOST"), 
            getenv("PGPORT"), getenv("PGDATABASE"));

    while ( 1 ) {
        tries++;
        sprintf(msg,"[%d/%d] Connecting to %s", tries, successes, dbhname);
        logmsg(msg);
        conn = PQconnectdb("connect_timeout=30");

        if (PQstatus(conn) == CONNECTION_BAD)
        {
            sprintf(msg, "Connection to database '%s' failed.", 
                    getenv("PGDATABASE"));
            logmsg(msg);
            sprintf(msg, "%s", PQerrorMessage(conn));
            logmsg(msg);
            PQfinish(conn);
            return 0;
        }

        successes++;
        res = PQexec(conn, "SELECT version()");
        if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
        {
            sprintf(msg, "SELECT query failed");
            logmsg(msg);
            PQclear(res);
            PQfinish(conn);
            return 0;
        }
        PQclear(res);
        sprintf(msg,"[%d/%d] Closing connection to %s", 
                tries, successes, get_dbhname(conn,dbhname));
        logmsg(msg);
        PQfinish(conn);
    }

    return 0;
}
---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
      subscribe-nomail command to [EMAIL PROTECTED] so that your
      message can get through to the mailing list cleanly

Reply via email to