This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Avoid res_nsend fd leaks


Hi!

res_nsend badly leaks filedescriptors.
A testcase is e.g.:

#include <netdb.h>
main()
{
  char * name = "acs.ac.sg";
  int i;

  for (i = 0; i < 1000; i++)
    gethostbyname(name);
}

The issue is that res_nclose clears _u._ext.nscount but it is initialized
only at the beginning of res_nsend, so if res_nclose is for some reason
called and res_nsend tries another nameserver and/or retries, next time
_u._ext.nscount will be 0 and thus res_nclose does not attempt to close any
sockets (and they get overwritten next time).
This patch attempts to solve this by separating two functions of nscount:
keeps it as count of IPv4 nameservers and moves the meaning that
initialization is needed on next res_nsend to new field nsinit.
Like this, res_nclose can be called as many times as it wishes from within
one res_nsend and no leaks happen.

2001-01-03  Jakub Jelinek  <jakub@redhat.com>

	* resolv/resolv.h (struct __res_state): Add nsinit field.
	* resolv/res_send.c (res_nsend): Use it instead of nscount.
	* resolv/res_init.c (__res_vinit): Initialize it.
	(res_nclose): Clear it instead of nscount.

--- libc/resolv/res_send.c.jj	Fri Aug 25 18:59:43 2000
+++ libc/resolv/res_send.c	Wed Jan  3 23:35:20 2001
@@ -394,7 +394,7 @@ res_nsend(res_state statp,
 	 * If the ns_addr_list in the resolver context has changed, then
 	 * invalidate our cached copy and the associated timing data.
 	 */
-	if (EXT(statp).nscount != 0) {
+	if (EXT(statp).nsinit) {
 		int needclose = 0;
 
 		if (EXT(statp).nscount != statp->nscount)
@@ -420,7 +420,7 @@ res_nsend(res_state statp,
 	/*
 	 * Maybe initialize our private copy of the ns_addr_list.
 	 */
-	if (EXT(statp).nscount == 0) {
+	if (EXT(statp).nsinit == 0) {
 #ifdef _LIBC
 		n = 0;
 #endif
@@ -454,6 +454,7 @@ res_nsend(res_state statp,
 #endif
 		}
 		EXT(statp).nscount = statp->nscount;
+		EXT(statp).nsinit = 1;
 #ifdef _LIBC
 		/* If holes left, free memory and set to NULL */
 		while (n < MAXNS) {
--- libc/resolv/res_init.c.jj	Wed Jan  3 22:45:30 2001
+++ libc/resolv/res_init.c	Wed Jan  3 23:33:50 2001
@@ -177,6 +177,7 @@ __res_vinit(res_state statp, int preinit
 	statp->_flags = 0;
 	statp->qhook = NULL;
 	statp->rhook = NULL;
+	statp->_u._ext.nsinit = 0;
 	statp->_u._ext.nscount = 0;
 #ifdef _LIBC
 	statp->_u._ext.nscount6 = 0;
@@ -544,5 +545,5 @@ res_nclose(res_state statp) {
 			statp->_u._ext.nssocks[ns] = -1;
 		}
 	}
-	statp->_u._ext.nscount = 0;
+	statp->_u._ext.nsinit = 0;
 }
--- libc/resolv/resolv.h.jj	Thu Aug 10 09:39:05 2000
+++ libc/resolv/resolv.h	Wed Jan  3 23:32:23 2001
@@ -154,6 +154,7 @@ struct __res_state {
 			u_int16_t		nstimes[MAXNS];	/* ms. */
 			int			nssocks[MAXNS];
 			u_int16_t		nscount6;
+			u_int16_t		nsinit;
 			struct sockaddr_in6	*nsaddrs[MAXNS];
 		} _ext;
 	} _u;

	Jakub

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]