Thread: PQisBusy() always busy

PQisBusy() always busy

From
bradg
Date:
It seems like PQisBusy() == 1 indefinitely after calling the asynchronous
function PQsendQueryParams().

I am using a method to check for the availability of asynchronous results
straight out of the latest PostgreSQL book by Korry and Susan Douglas. It
uses select() and then FD_ISSET on the connection socket, then calls both
PQconsumeInput() and PQisBusy().

For some reason, the value for PQisBusy() is always 1, no matter how long I
let the program run.

I'm just wondering if anyone can point me in the right direction. For what
it's worth. I'm programming in OS X 10.7 with Xcode 4.1 using the PostgreSQL
files from the EnterpriseDB one-click installer.

Here's the function:

bool is_result_ready( PGconn * connection )
{
    int            my_socket;
    struct timeval    timer;
    fd_set        read_mask;

    if( PQisBusy( connection ) == FALSE )
        return( TRUE );

    my_socket = PQsocket( connection );

    timer.tv_sec  = (time_t)1;
    timer.tv_usec = 0;

    FD_ZERO( &read_mask );
    FD_SET( my_socket, &read_mask );

    if( select( my_socket + 1, &read_mask, NULL, NULL, &timer ) == 0 )
    {
        return( FALSE );
    }
    else if( FD_ISSET( my_socket, &read_mask ))
    {
        PQconsumeInput( connection );

        if( PQisBusy( connection ))    <------ THIS PQisBusy() ALWAYS
RETURNS 1
            return( FALSE );
        else
            return( TRUE );
    }
    else
    {
        return( FALSE );
    }
}


Thanks in advance for any insight.

Brad

--
View this message in context: http://postgresql.1045698.n5.nabble.com/PQisBusy-always-busy-tp4793847p4793847.html
Sent from the PostgreSQL - novice mailing list archive at Nabble.com.

Re: PQisBusy() always busy

From
Merlin Moncure
Date:
On Mon, Sep 12, 2011 at 6:16 AM, bradg <bg4all@me.com> wrote:
> It seems like PQisBusy() == 1 indefinitely after calling the asynchronous
> function PQsendQueryParams().
>
> I am using a method to check for the availability of asynchronous results
> straight out of the latest PostgreSQL book by Korry and Susan Douglas. It
> uses select() and then FD_ISSET on the connection socket, then calls both
> PQconsumeInput() and PQisBusy().
>
> For some reason, the value for PQisBusy() is always 1, no matter how long I
> let the program run.
>
> I'm just wondering if anyone can point me in the right direction. For what
> it's worth. I'm programming in OS X 10.7 with Xcode 4.1 using the PostgreSQL
> files from the EnterpriseDB one-click installer.
>
> Here's the function:
>
> bool is_result_ready( PGconn * connection )
> {
>    int                 my_socket;
>    struct timeval      timer;
>    fd_set              read_mask;
>
>    if( PQisBusy( connection ) == FALSE )
>        return( TRUE );
>
>    my_socket = PQsocket( connection );
>
>    timer.tv_sec  = (time_t)1;
>    timer.tv_usec = 0;
>
>    FD_ZERO( &read_mask );
>    FD_SET( my_socket, &read_mask );
>
>    if( select( my_socket + 1, &read_mask, NULL, NULL, &timer ) == 0 )
>    {
>        return( FALSE );
>    }
>    else if( FD_ISSET( my_socket, &read_mask ))
>    {
>        PQconsumeInput( connection );
>
>        if( PQisBusy( connection ))    <------ THIS PQisBusy() ALWAYS
> RETURNS 1
>            return( FALSE );
>        else
>            return( TRUE );
>    }
>    else
>    {
>        return( FALSE );
>    }
> }
>
>
> Thanks in advance for any insight.

You are not checking the return of PQconsumeInput -- if there is a
problem with the connection, you won't catch the change to the
internal asyncStatus flag because it only gets changed from data
returned over the socket. Try changing your code to watch for
PQconsumeInput return value, and displaying/handling the connection
error if there is a problem.

per docs: "PQconsumeInput normally returns 1 indicating "no error",
but returns 0 if there was some kind of trouble (in which case
PQerrorMessage can be consulted). Note that the result does not say
whether any input data was actually collected. After calling
PQconsumeInput, the application can check PQisBusy and/or PQnotifies
to see if their state has changed."

merlin

Re: PQisBusy() always busy

From
bradg
Date:
Thanks Merlin.

I added the piece to check PQconsumeInput(). Unfortunately it has not solved
my problem. It returns 1 indicating "no error" and PQisBusy() still returns
1 indefinitely.

Here's the updated code:


bool is_result_ready( PGconn * connection )
{
    int                 my_socket;
    struct timeval      timer;
    fd_set              read_mask;

    if( PQisBusy( connection ) == FALSE )
        return( TRUE );

    my_socket = PQsocket( connection );

    timer.tv_sec  = (time_t)1;
    timer.tv_usec = 0;

    FD_ZERO( &read_mask );
    FD_SET( my_socket, &read_mask );

    if( select( my_socket + 1, &read_mask, NULL, NULL, &timer ) == 0 )
    {
        return( FALSE );
    }
    else if( FD_ISSET( my_socket, &read_mask ))
    {
        if (PQconsumeInput( connection ))
        {
            if( PQisBusy( connection ))
                return( FALSE );
            else
                return( TRUE );
        }
        else
        {
            printf("ERROR with PQconsumeInput(): %s\n",
PQerrorMessage(connection));
            return ( FALSE );
        }
    }
    else
    {
        return( FALSE );
    }
}

--
View this message in context: http://postgresql.1045698.n5.nabble.com/PQisBusy-always-busy-tp4793847p4794992.html
Sent from the PostgreSQL - novice mailing list archive at Nabble.com.

Re: PQisBusy() always busy

From
Merlin Moncure
Date:
On Mon, Sep 12, 2011 at 12:21 PM, bradg <bg4all@me.com> wrote:
> Thanks Merlin.
>
> I added the piece to check PQconsumeInput(). Unfortunately it has not solved
> my problem. It returns 1 indicating "no error" and PQisBusy() still returns
> 1 indefinitely.
>
> Here's the updated code:
>
>
> bool is_result_ready( PGconn * connection )
> {
>    int                 my_socket;
>    struct timeval      timer;
>    fd_set              read_mask;
>
>    if( PQisBusy( connection ) == FALSE )
>        return( TRUE );
>
>    my_socket = PQsocket( connection );
>
>    timer.tv_sec  = (time_t)1;
>    timer.tv_usec = 0;
>
>    FD_ZERO( &read_mask );
>    FD_SET( my_socket, &read_mask );
>
>    if( select( my_socket + 1, &read_mask, NULL, NULL, &timer ) == 0 )
>    {
>        return( FALSE );
>    }
>    else if( FD_ISSET( my_socket, &read_mask ))
>    {
>        if (PQconsumeInput( connection ))
>        {
>            if( PQisBusy( connection ))
>                return( FALSE );
>            else
>                return( TRUE );
>        }
>        else
>        {
>            printf("ERROR with PQconsumeInput(): %s\n",
> PQerrorMessage(connection));
>            return ( FALSE );
>        }
>    }
>    else
>    {
>        return( FALSE );
>    }
> }

hm -- it's working for me. test program (plus some extra logging) attached:

output:
select returned zero
i=0
not busy!
i=1

merlin

Attachment

Re: PQisBusy() always busy

From
bradg
Date:
My output is:

i=1
i=1

The very first PQisBusy() inside is_result_ready() — right after the
variable declarations at the top — returns NO before even getting to the
select() / FD_ISSET() portion of the code.

--
View this message in context: http://postgresql.1045698.n5.nabble.com/PQisBusy-always-busy-tp4793847p4795490.html
Sent from the PostgreSQL - novice mailing list archive at Nabble.com.

Re: PQisBusy() always busy

From
Merlin Moncure
Date:
On Mon, Sep 12, 2011 at 2:04 PM, bradg <bg4all@me.com> wrote:
> My output is:
>
> i=1
> i=1
>
> The very first PQisBusy() inside is_result_ready() — right after the
> variable declarations at the top — returns NO before even getting to the
> select() / FD_ISSET() portion of the code.

hm, did you double check the connection?  I did a sloppy connect with
no error handling -- maybe that's the issue -- hopefully that's the
issue.  If you pull the result, is it coming back valid?

merlin

Re: PQisBusy() always busy

From
bradg
Date:
Well, my output matches yours now:

select returned zero
i=0
not busy!
i=1

Thanks for helping me eliminate that part of my code.

Just curious... If I can't get to the bottom of my problem, is it safe to
put PQexecParams() and PQexecPrepared() in a separate thread?

--
View this message in context: http://postgresql.1045698.n5.nabble.com/PQisBusy-always-busy-tp4793847p4795679.html
Sent from the PostgreSQL - novice mailing list archive at Nabble.com.

Re: PQisBusy() always busy

From
Merlin Moncure
Date:
On Mon, Sep 12, 2011 at 2:48 PM, bradg <bg4all@me.com> wrote:
> Well, my output matches yours now:
>
> select returned zero
> i=0
> not busy!
> i=1
>
> Thanks for helping me eliminate that part of my code.
>
> Just curious... If I can't get to the bottom of my problem, is it safe to
> put PQexecParams() and PQexecPrepared() in a separate thread?

er, if you have an undiagnosed problem in your code, I am really
struggling with the leap of logic that you are somehow better off
using threads :-).   given the choice of asynchronous, single threaded
programming and multi-threaded, I'll go asynchronous without
hesitation unless I have a very, very good reason not to.   Better to
understand the issue completely now.

merlin

Re: PQisBusy() always busy

From
bradg
Date:
I know it must sound stupid, but...

My code is simple and works exactly the way I want it to with the blocking
functions PQexecParams() and PQexecPrepared(). I'm trying to extend it with
asynchronous functions so I can execute queries both ways.

But I seem to be losing a lot of time on this so my thought was to just use
the blocking functions in a separate thread. Hence my question whether or
not they are thread safe.

Do you know if they are?

Thanks

--
View this message in context: http://postgresql.1045698.n5.nabble.com/PQisBusy-always-busy-tp4793847p4796276.html
Sent from the PostgreSQL - novice mailing list archive at Nabble.com.

Re: PQisBusy() always busy

From
Merlin Moncure
Date:
On Mon, Sep 12, 2011 at 5:44 PM, bradg <bg4all@me.com> wrote:
> I know it must sound stupid, but...
>
> My code is simple and works exactly the way I want it to with the blocking
> functions PQexecParams() and PQexecPrepared(). I'm trying to extend it with
> asynchronous functions so I can execute queries both ways.
>
> But I seem to be losing a lot of time on this so my thought was to just use
> the blocking functions in a separate thread. Hence my question whether or
> not they are thread safe.
>
> Do you know if they are?

I reiterate that it is dangerous to use threads unless you have a very
good reason to do so.  It makes everything more complex: debugging,
logging, etc. Feel free to try it, but...

libpq is thread safe if so compiled but it is your responsibility to
ensure that only one thread accesses a connection object at once.  Hm.
You *are* aware that with asynchronous connections you must fully
retrieve a result before sending the next query?  The asynchronous
model is generally meant for keeping multiple connection objects with
each having at most one running query.  It also allows for low latency
processing of asynchronous notification events coming back from the
server, keeping the process under your control so you can respond to
user UI actions, etc.

merlin

Re: PQisBusy() always busy

From
bradg
Date:
Thanks for your thoughtful, detailed response. I also took your warnings to
heart and resolved the underlying problem in my code without resorting to
threads. I have both the blocking and nonblocking functions working without
any issues.

Except one. Speed.

When I use the blocking function on a select query for 102 records, the time
is 0.645284 seconds. When I use the nonblocking version, the time is
52.000426 seconds. The application pgAdmin3 takes 1.6 seconds.

Does that seem right?

--
View this message in context: http://postgresql.1045698.n5.nabble.com/PQisBusy-always-busy-tp4793847p4800947.html
Sent from the PostgreSQL - novice mailing list archive at Nabble.com.

Re: PQisBusy() always busy

From
Merlin Moncure
Date:
On Tue, Sep 13, 2011 at 7:50 PM, bradg <bg4all@me.com> wrote:
> Thanks for your thoughtful, detailed response. I also took your warnings to
> heart and resolved the underlying problem in my code without resorting to
> threads. I have both the blocking and nonblocking functions working without
> any issues.
>
> Except one. Speed.
>
> When I use the blocking function on a select query for 102 records, the time
> is 0.645284 seconds. When I use the nonblocking version, the time is
> 52.000426 seconds. The application pgAdmin3 takes 1.6 seconds.
>
> Does that seem right?

It does not.  In fact, if you look at the internal libpq code, you'll
notice that they all run through the same internal call -- something
is amiss. What happens when you immediately try to get the result
after sending the query?

merlin