I have been having some trouble with using PQnotifies and the select
function. When I run the program below, the select function returns
early (before 5sec) when I send it a notify; but once the select
function runs out the first time (after 5sec), then no matter how many
time I send anotify the select does not return until after the full 5
secs.
----
$ gcc -o testlibpq testlibpq.c -lpq -I/usr/include/postgresql
$ DBHOST=db DB=gpdb ./testlibpq
Calling select(4,&rfds(3),NULL,NULL,5.0)
Return select(4,&rfds(3),NULL,NULL,3.430000)
ASYNC NOTIFY of 'tbl2' from backend pid '9764' received
Calling select(4,&rfds(3),NULL,NULL,5.0)
Return select(4,&rfds(3),NULL,NULL,4.120000)
ASYNC NOTIFY of 'tbl2' from backend pid '9764' received
Calling select(4,&rfds(3),NULL,NULL,5.0)
Return select(4,&rfds(3),NULL,NULL,3.100000)
ASYNC NOTIFY of 'tbl2' from backend pid '9764' received
Calling select(4,&rfds(3),NULL,NULL,5.0) <- let time run out
Return select(4,&rfds(3),NULL,NULL,0.0)
Calling select(4,&rfds(3),NULL,NULL,5.0) <- send many notify, but none were heard until later
Return select(4,&rfds(3),NULL,NULL,0.0)
ASYNC NOTIFY of 'tbl2' from backend pid '9764' received
ASYNC NOTIFY of 'tbl2' from backend pid '9764' received
ASYNC NOTIFY of 'tbl2' from backend pid '9764' received
ASYNC NOTIFY of 'tbl2' from backend pid '9764' received
Calling ...
----
See after the select runs out the first time, it never interupts early
again.
any throughts?
james
+++++++++++++++ testlibpq.c +++++++++++++
// gcc -o testlibpq testlibpq.c -lpq -I/usr/include/postgresql
// DBHOST=db DB=test ./testlibpq
#include <stdio.h>
#include "libpq-fe.h"
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
main()
{
char *pghost, *pgport, *pgoptions, *pgtty;
char *dbName;
int nFields;
int i, j;
PGconn *conn;
PGresult *res;
PGnotify *notify;
fd_set rfds;
struct timeval tv;
int pqfd;
pghost = getenv("DBHOST"); /* host name of the backend server */
pgport = NULL; /* port of the backend server */
pgoptions = NULL; /* special options to start up the backend
* server */
pgtty = NULL; /* debugging tty for the backend server */
dbName = getenv("DB"); /* change this to the name of your test
* database */
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
if (PQstatus(conn) == CONNECTION_BAD) {
fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
fprintf(stderr, "%s", PQerrorMessage(conn));
PQfinish(conn);
exit(1);
}
pqfd = PQsocket(conn); /* Set file handle to PQ socket */
FD_ZERO(&rfds);
FD_SET(pqfd, &rfds); /* then add it to the fd set */
res = PQexec(conn, "LISTEN TBL2");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "LISTEN command failed\n");
PQclear(res);
PQfinish(conn);
exit(1);
}
PQclear(res);
while (1) {
tv.tv_sec = 5;
tv.tv_usec = 0;
fprintf(stderr, "Calling select(%d,&rfds(%d),NULL,NULL,%d.%d)\n",
pqfd + 1, pqfd, tv.tv_sec, tv.tv_usec);
select(pqfd + 1, &rfds, NULL, NULL, &tv);
fprintf(stderr, "Return select(%d,&rfds(%d),NULL,NULL,%d.%d)\n",
pqfd + 1, pqfd, tv.tv_sec, tv.tv_usec);
PQconsumeInput(conn);
while ((notify = PQnotifies(conn)) != NULL) {
fprintf(stderr,
"ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
notify->relname, notify->be_pid);
free(notify);
}
}
PQfinish(conn);
return 0;
}