Обсуждение: PQisBusy() always busy
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.
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
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.
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
Вложения
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.
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
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.
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
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.
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
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.
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