* Bruce Momjian wrote:
> I think what you are seeing is that the getaddrinfo memory is placed in
> the PGconn structure that isn't freed until PQclear is called.  Does
> your test call PQclear()?

s/PQclear/PQfinish/
It does call PQclear on the result, and PQfinish on the connection.
The code is attached.

With postgres doing the dns lookup:
fubar:~# while true; do ps aux|grep -v grep|grep test; sleep 30; done
root      3245  3.6  0.2  4056 1352 pts/3    S+   10:37   0:01 ./test
root      3245  3.6  0.3  4056 1456 pts/3    S+   10:37   0:02 ./test
root      3245  3.7  0.3  4184 1560 pts/3    S+   10:37   0:03 ./test
root      3245  3.7  0.3  4312 1668 pts/3    R+   10:37   0:04 ./test
root      3245  3.6  0.3  4440 1760 pts/3    S+   10:37   0:05 ./test

with an output of:
called PQconnectdb: 0x804a008
called PQexec: 0x80dcbe0
calling PQclear: 0x80dcbe0
calling PQfinish: 0x804a008
...
called PQconnectdb: 0x804a008
called PQexec: 0x80dcea0
calling PQclear: 0x80dcea0
calling PQfinish: 0x804a008
...
called PQconnectdb: 0x804a008
called PQexec: 0x80dd620
calling PQclear: 0x80dd620
calling PQfinish: 0x804a008
...

and valgrind complaining about lost blocks:
==3290== 35224 bytes in 1258 blocks are definitely lost in loss record 8 of 8
==3290==    at 0x1B90459D: malloc (vg_replace_malloc.c:130)
==3290==    by 0x1BC38E3B: (within /lib/tls/i686/cmov/libresolv-2.3.2.so)
==3290==    by 0x1BC37B92: __libc_res_nquery (in 
/lib/tls/i686/cmov/libresolv-2.3.2.so)
==3290==    by 0x1BC38289: (within /lib/tls/i686/cmov/libresolv-2.3.2.so)
==3290==    by 0x1BC37E8F: __libc_res_nsearch (in 
/lib/tls/i686/cmov/libresolv-2.3.2.so)
==3290==    by 0x1BDA307D: ???
==3290==    by 0x1B9EFA65: (within /lib/tls/i686/cmov/libc-2.3.2.so)
==3290==    by 0x1B9F0673: getaddrinfo (in /lib/tls/i686/cmov/libc-2.3.2.so)
==3290==    by 0x1B925701: getaddrinfo_all (in /usr/lib/libpq.so.3.1)
==3290==    by 0x1B916F0B: (within /usr/lib/libpq.so.3.1)
==3290==    by 0x1B9164B9: PQconnectStart (in /usr/lib/libpq.so.3.1)
==3290==    by 0x1B916441: PQconnectdb (in /usr/lib/libpq.so.3.1)


With the IP in the host field:
fubar:~# while true; do ps aux|grep -v grep|grep test; sleep 30; done
root      3312  1.4  0.2  3872 1092 pts/3    S+   10:42   0:00 ./test
root      3312  1.6  0.2  3872 1092 pts/3    S+   10:42   0:00 ./test
root      3312  1.9  0.2  3872 1092 pts/3    S+   10:42   0:01 ./test
root      3312  2.0  0.2  3872 1092 pts/3    S+   10:42   0:01 ./test
root      3312  2.0  0.2  3872 1092 pts/3    S+   10:42   0:02 ./test

output:
called PQconnectdb: 0x804a008
called PQexec: 0x80525b8
calling PQclear: 0x80525b8
calling PQfinish: 0x804a008
...
called PQconnectdb: 0x804a008
called PQexec: 0x80525b8
calling PQclear: 0x80525b8
calling PQfinish: 0x804a008
...
called PQconnectdb: 0x804a008
called PQexec: 0x80525b8
calling PQclear: 0x80525b8
calling PQfinish: 0x804a008
...

and no leaking output from valgrind.

Best regards,
 Karsten Desler
#include <postgresql/libpq-fe.h>
#include <stdio.h>

// gcc -lpq -o test test.c

static const char *conninfo = "host=xxx.xxx.xx.xx port=5432 dbname=xxx user=xxx password=xxx connect_timeout=30";
// static const char *conninfo = "host=db.xxx.de port=5432 dbname=xxx user=xxx password=xxx connect_timeout=30";

static int fetch_from_database(void)
{
	PGconn *conn;
	PGresult *res;
	char sql[32768];
	int c_username, c_ip;
	int ret = -1;
	unsigned int max, i;

	conn = PQconnectdb(conninfo);
	printf("called PQconnectdb: %p\n", conn);
	if (!conn) {
		printf("connection failed\n");
		goto out_finish;
	}

	snprintf(sql, sizeof(sql), "SELECT username,ip FROM extras WHERE server=(SELECT id FROM servers WHERE IP='xxx.xxx.xx.xx') ORDER BY username");
	res = PQexec(conn, sql);
	printf("called PQexec: %p\n", res);
	if (PQresultStatus(res) != PGRES_TUPLES_OK) {
		printf("couldn't get data\n");
		goto out;
	}

	max = (unsigned int)PQntuples(res);
	if (max == 0) { 
		ret = 0;
		goto out;
	}

	if (max > 64) {
		printf("too many results\n");
		goto out;
	}

	c_username = PQfnumber(res, "username");
	c_ip = PQfnumber(res, "ip");

	if (c_username == -1 || c_ip == -1) {
		printf("weird table structure found\n");
		goto out;
	}

	for (i = 0; i < max; i++) {
		(void)PQgetvalue(res, i, c_username);
		(void)PQgetvalue(res, i, c_ip);
	}

	ret = 0;
out:
	printf("calling PQclear: %p\n", res);
	PQclear(res);
out_finish:
	printf("calling PQfinish: %p\n", conn);
	PQfinish(conn);
	res = NULL;
	conn = NULL;

	return ret;
}

int main(void)
{
	while(fetch_from_database() == 0);
	return 0;
}
---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
       choose an index scan if your joining column's datatypes do not
       match

Reply via email to