This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][BZ #14719] Return EAI_SYSTEM from getaddrinfo if we run outof fds


Hi,

As described in the bug report, the current behaviour for getaddrinfo
when it runs out of file descriptors is to return EAI_NOTFOUND, which
is incorrect.  Since a system error has occurred, it should be
returning EAI_SYSTEM so that the real cause of the failure could be
seen from errno.  Attached patch does that.  Tested on x86_64 Fedora
16 for AF_INET, AF_UNSPEC and AF_INET6.  OK to commit?

Regards,
Siddhesh

ChangeLog:

	[BZ #14719]
	* nss/getXXbyYY_r.c (INTERNAL (REENTRANT_NAME)): Set h_errno to
	NETDB_INTERNAL when NSS_STATUS_UNAVAIL.
	* resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname3_r): Set
	h_errno to NETDB_INTERNAL when errno is EMFILE or ENFILE.
	(_nss_dns_gethostbyname4_r): Likewise.
	* sysdeps/posix/getaddrinfo.c (gaih_inet): Set result to
	EAI_SYSTEM if NSS_STATUS_UNAVAIL.
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
index f296ed1..dfa0dfc 100644
--- a/nss/getXXbyYY_r.c
+++ b/nss/getXXbyYY_r.c
@@ -284,8 +284,13 @@ done:
 #endif
   *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
 #ifdef NEED_H_ERRNO
-  if (status != NSS_STATUS_SUCCESS && ! any_service)
-    /* We were not able to use any service.  */
+  if (status == NSS_STATUS_UNAVAIL)
+    /* Either we failed to lookup the functions or the functions themselves had a
+       system error.  Set NETDB_INTERNAL here to let the caller know that the
+       errno may have the real reason for failure.  */
+      *h_errnop = NETDB_INTERNAL;
+  else if (status != NSS_STATUS_SUCCESS && !any_service)
+    /* We were no able to use any service.  */
     *h_errnop = NO_RECOVERY;
 #endif
 #ifdef POSTPROCESS
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 6b62c05..102afb2 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -199,6 +199,10 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
 	  status = NSS_STATUS_TRYAGAIN;
 	  h_errno = TRY_AGAIN;
 	  break;
+	/* System has run out of file descriptors.  */
+	case EMFILE:
+	case ENFILE:
+	  h_errno = NETDB_INTERNAL;
 	case ECONNREFUSED:
 	case ETIMEDOUT:
 	  status = NSS_STATUS_UNAVAIL;
@@ -311,14 +315,25 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
 			      &ans2p, &nans2p, &resplen2);
   if (n < 0)
     {
-      if (errno == ESRCH)
+      switch (errno)
 	{
+	case ESRCH:
 	  status = NSS_STATUS_TRYAGAIN;
 	  h_errno = TRY_AGAIN;
+	  break;
+	/* System has run out of file descriptors.  */
+	case EMFILE:
+	case ENFILE:
+	  h_errno = NETDB_INTERNAL;
+	case ECONNREFUSED:
+	case ETIMEDOUT:
+	  status = NSS_STATUS_UNAVAIL;
+	  break;
+	default:
+	  status = NSS_STATUS_NOTFOUND;
+	  break;
 	}
-      else
-	status = (errno == ECONNREFUSED
-		  ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND);
+
       *herrnop = h_errno;
       if (h_errno == TRY_AGAIN)
 	*errnop = EAGAIN;
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 672571e..ad5ae01 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -1049,6 +1049,12 @@ gaih_inet (const char *name, const struct gaih_service *service,
 
 	  _res.options |= old_res_options & RES_USE_INET6;
 
+	  if (status == NSS_STATUS_UNAVAIL)
+	    {
+	      result = GAIH_OKIFUNSPEC | -EAI_SYSTEM;
+	      goto free_and_return;
+	    }
+
 	  if (no_data != 0 && no_inet6_data != 0)
 	    {
 	      /* If both requests timed out report this.  */

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