Solved PQconnectdb() causes program to crash

I'm a little all over the place with this question so please read to the end. This is a program that connects to the database but really wasn't as I just found out.

I have a program in C that talks to nginx, locally, to serve web pages via FastCGI and this works well. I use spawn-fcgi for the FastCGI interface.

I want to attach a database, postgreSQL, and talk to that via unix sockets. Using a short, standalone test program, I'm able to connect to postgres, do a query and return correct results.


Code:
PGconn* connect_db(void) {
 
        PGconn *conn = PQconnectdb("user=pgsql dbname=mydb host=/tmp password=mypass
                       port=5432");
 
        if(PQstatus(conn) != CONNECTION_OK) {
            return 0;
        } else return conn;
    }


    int
    main(void){
 
        PGconn *db = NULL;
        db = connect_db();
 
        if(PQstatus(db) != CONNECTION_OK) {
            printf("%s", "Connection failed");
            PQfinish(db);
            return 0;
        }
        printf("OK");
 
        PGresult *result = PQexec(db,"select a bunch of stuff here;");
        printf("%s",PQgetvalue(result,0,0));
    }

When I use the same code as above in my program for the web site, however, my program exits with signal 11, segfault, and brings spawn-fcgi down with it causing a 502 HTTP response. The nginx error.log says:

> upstream prematurely closed connection while reading response header
> from upstream, client: 127.0.0.1, server: localhost upstream:
> "fastcgi://unix:/var/run/fcgi-sock.fcgi:", host: "localhost"

The program exits when I try to do the connect. Leave that call to PQconnectdb() out and the program does not crash. I do not include the query.

One thought I had is there might be a permissions issue since nginx runs as www:www while postgresql runs as user pgsql:wheel but I don't know what to do with that and if that's the whole issue. At least the socket in /tmp says the owner is pgsql:wheel.

I have not made any changes to postgresql.conf

So I'm hoping someone recognizes the problem and help me out.

**EDIT:** I changed my running server code to call PQconnectdb directly.


Code:
PGconn *db = NULL;
    db = PQconnectdb("user=pgsql dbname=mydb port=5432");

Including that call causes the program to crash and nginx debug still shows upstream closing prematurely.

I question whether I still have a missing setting in the postgresql config but, from what I read, this should work out of the box.
 
I'm not much of a programmer but if connect_db fails it returns a 0. I'm not sure what happens with PQStatus() if you feed it a 0 instead of a pointer to a structure. Note that 0 and NULL are different.
 
I'm not much of a programmer but if connect_db fails it returns a 0. I'm not sure what happens with PQStatus() if you feed it a 0 instead of a pointer to a structure. Note that 0 and NULL are different.

I had the same idea, however, NULL is defined in /usr/include/sys/_null.h which is included by /usr/include/stddef.h:
Code:
#if !defined(__cplusplus)
#define    NULL    ((void *)0)
#else
#if __cplusplus >= 201103L
#define    NULL    nullptr
#elif defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4
#define    NULL    __null
#else
#if defined(__LP64__)
#define    NULL    (0L)
#else
#define    NULL    0
#endif    /* __LP64__ */
#endif    /* __GNUG__ */
#endif    /* !__cplusplus */
That means, in C on FreeBSD, 0 is the same as NULL, and I verified that PQstatus() happily accepts (0 and NULL for that matter), so I don't believe that PQstatus() crashes.

drhowarddrfine, can you attach your program to the debugger, and set a breakpoint to the line where you call connect_db()?

Is your application a threaded one? I yes, you might want to verify, if one of the impeding conditions applies to your program:
https://www.postgresql.org/docs/9.3/static/libpq-threading.html
 
No, it's not threaded. I tried using gdb to attach to it but that failed, perhaps cause I used clang, so I tried lldb, which works, but it has different commands and I haven't figured that all out before I went to bed.

I'm also aware of the NULL != 0 thing.

The frustrating part is, I wrote all my code a few months ago and thought this part was working but only found out yesterday I was fooled and it's not. Now that I'm running out of time, I'm anxious and having trouble focusing on the fundamentals (and just don't want to have to re-read all that stuff again).
 
No, it's not threaded. I tried using gdb to attach to it but that failed, perhaps cause I used clang, so I tried lldb, which works, but it has different commands and I haven't figured that all out before I went to bed.

Many people don't know, however, lldb(1) got a ncurses kind of gui mode. You will be amazed how easy it is to use it. In one of my recent posts, I showed an example of this (scroll down to the very bottom of that post):
https://forums.freebsd.org/threads/58460/

EDIT:
In my experience the libpq routines never crashed my programs when establishing a connection. Crashes occurred, though, when I tried to access query results and forgot to check whether these really exist. You'll find out easily the cause for this kind of crashes with the debugger.
 
Found the problem. It's always something stupid. I mistyped a function and it's name wound up being send() instead of send_page_data(). So I presume it was trying to call the system call send(), thus the cause of my problem.

Funny how I found it. I was reading a tutorial on the lldb web site and trying a few commands and thought I was doing something wrong (again) cause I was landing in a place in the code that didn't make any sense. Listing the source at that point showed the function name and that's how I caught it.

If nothing else, I feel better that it wasn't something like I was way off in my understanding of how things work. Most of my struggles come about from staring at the screen too long or simple typos. I told the story of many years ago when I spent three days on a bug caused by a missing dot in an assembly language instruction. Other times I make big discoveries just walking to the bathroom and back.
 
Back
Top