This is the mail archive of the libc-hacker@cygnus.com 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]

A RPC patch for glibc


Hi,

I finally figured out why I couldn't shutdown my machine. The problem
is we set 60 second timeout in RPC. But when all network interface are
down, we may have many 60 second timeouts. It happens in the shutdown
and reboot sequences. So it gives an impresson that it takes forever to
shutdown when NIS is enabled and there are some processes with PIDs
which are not in /etc/passwd.

This patch tries to fix it. When there is a timeout in RPC, it checks
if there is any network interface up. If not, it returns immediately.

Thanks.

H.J.
----
Index: sunrpc/clnt_udp.c
===================================================================
RCS file: /local/work/cvs/gnu/glibc/sunrpc/clnt_udp.c,v
retrieving revision 1.1.1.12
diff -u -p -r1.1.1.12 clnt_udp.c
--- sunrpc/clnt_udp.c	1998/11/19 18:46:59	1.1.1.12
+++ sunrpc/clnt_udp.c	1999/04/12 21:13:55
@@ -48,6 +48,7 @@ static char sccsid[] = "@(#)clnt_udp.c 1
 #include <netdb.h>
 #include <errno.h>
 #include <rpc/pmap_clnt.h>
+#include <net/if.h>
 
 extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *);
 extern u_long _create_xid (void);
@@ -214,6 +215,33 @@ clntudp_create (raddr, program, version,
 			    UDPMSGSIZE, UDPMSGSIZE);
 }
 
+static int
+is_network_up (int sock)
+{
+  struct ifconf ifc;
+  char buf [UDPMSGSIZE];
+  struct ifreq ifreq, *ifr;
+  int n;
+
+  ifc.ifc_len = sizeof (buf);
+  ifc.ifc_buf = buf;
+  if (__ioctl(sock, SIOCGIFCONF, (char *) &ifc) == 0)
+    {
+      ifr = ifc.ifc_req;
+      for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++)
+	{
+	  ifreq = *ifr;
+	  if (__ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0)
+	    break;
+	    
+	  if ((ifreq.ifr_flags & IFF_UP)
+	      && ifr->ifr_addr.sa_family == AF_INET)
+	    return 1;
+	}
+    }
+  return 0;
+}
+
 static enum clnt_stat
 clntudp_call (cl, proc, xargs, argsp, xresults, resultsp, utimeout)
      CLIENT *cl;	/* client handle */
@@ -239,6 +267,7 @@ clntudp_call (cl, proc, xargs, argsp, xr
   bool_t ok;
   int nrefreshes = 2;		/* number of times to refresh cred */
   struct timeval timeout;
+  int anyup;			/* any network interface up */
 
   if (cu->cu_total.tv_usec == -1)
     {
@@ -294,12 +323,19 @@ send_again:
   reply_msg.acpted_rply.ar_results.proc = xresults;
   fd.fd = cu->cu_sock;
   fd.events = POLLIN;
+  anyup = 0;
   for (;;)
     {
       switch (__poll(&fd, 1, milliseconds))
 	{
 
 	case 0:
+	  if (anyup == 0)
+	    anyup = is_network_up (cu->cu_sock);
+
+	  if (!anyup)
+	    return (cu->cu_error.re_status = RPC_CANTRECV);
+
 	  time_waited.tv_sec += cu->cu_wait.tv_sec;
 	  time_waited.tv_usec += cu->cu_wait.tv_usec;
 	  while (time_waited.tv_usec >= 1000000)


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