Solved PQconnectdb() causes program to crash

drhowarddrfine

Son of Beastie

Reaction score: 2,732
Messages: 4,647

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.
 

SirDice

Administrator
Staff member
Administrator
Moderator

Reaction score: 14,036
Messages: 40,763

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.
 

obsigna

Daemon

Reaction score: 982
Messages: 1,370

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
 
OP
D

drhowarddrfine

Son of Beastie

Reaction score: 2,732
Messages: 4,647

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).
 

obsigna

Daemon

Reaction score: 982
Messages: 1,370

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.
 
OP
D

drhowarddrfine

Son of Beastie

Reaction score: 2,732
Messages: 4,647

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.
 
Top