rx: For AFS_RXERRQ_ENV, retry sendmsg on error
[openafs.git] / src / rx / rx_lwp.c
index 2020c41..dfeb674 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
+#include <roken.h>
 
-# include <sys/types.h>                /* fd_set on older platforms */
-# include <errno.h>
-# include <signal.h>
-#ifdef AFS_NT40_ENV
-# include <winsock2.h>
-#else
-# include <unistd.h>           /* select() prototype */
-# include <sys/time.h>         /* struct timeval, select() prototype */
-# ifndef FD_SET
-#  include <sys/select.h>      /* fd_set on newer platforms */
-# endif
-# include <sys/socket.h>
+#ifdef HAVE_SYS_FILE_H
 # include <sys/file.h>
-# include <netdb.h>
-# include <sys/stat.h>
-# include <netinet/in.h>
-# include <net/if.h>
-# include <sys/ioctl.h>
-# include <sys/time.h>
 #endif
-# include "rx.h"
-# include "rx_globals.h"
-# include <lwp.h>
+
+#ifndef AFS_PTHREAD_ENV
+
+#include <lwp.h>
+
+#include "rx.h"
+#include "rx_atomic.h"
+#include "rx_globals.h"
+#include "rx_internal.h"
+#include "rx_stats.h"
+#ifdef AFS_NT40_ENV
+#include "rx_xmit_nt.h"
+#endif
 
 #define MAXTHREADNAMELENGTH 64
 
@@ -178,14 +172,16 @@ rxi_ListenerProc(fd_set * rfds, int *tnop, struct rx_call **newcallp)
     nextPollTime = 0;
     code = LWP_CurrentProcess(&pid);
     if (code) {
-       fprintf(stderr, "rxi_Listener: Can't get my pid.\n");
-       exit(1);
+       osi_Panic("rxi_Listener: Can't get my pid.\n");
     }
     rx_listenerPid = pid;
     if (swapNameProgram)
        (*swapNameProgram) (pid, "listener", &name[0]);
 
     for (;;) {
+        /* See if a check for additional packets was issued */
+        rx_CheckPackets();
+
        /* Grab a new packet only if necessary (otherwise re-use the old one) */
        if (p) {
            rxi_RestoreDataBufs(p);
@@ -209,7 +205,8 @@ rxi_ListenerProc(fd_set * rfds, int *tnop, struct rx_call **newcallp)
            tv.tv_usec = cv.usec;
            tvp = &tv;
        }
-       rx_stats.selects++;
+       if (rx_stats_active)
+           rx_atomic_inc(&rx_stats.selects);
 
        *rfds = rx_selectMask;
 
@@ -331,14 +328,13 @@ rx_ListenerProc(void *dummy)
        newcall = NULL;
        threadID = -1;
        rxi_ListenerProc(rfds, &threadID, &newcall);
-       /* assert(threadID != -1); */
-       /* assert(newcall != NULL); */
+       /* osi_Assert(threadID != -1); */
+       /* osi_Assert(newcall != NULL); */
        sock = OSI_NULLSOCKET;
        rxi_ServerProc(threadID, newcall, &sock);
-       /* assert(sock != OSI_NULLSOCKET); */
+       /* osi_Assert(sock != OSI_NULLSOCKET); */
     }
-    /* not reached */
-    return NULL;
+    AFS_UNREACHED(return(NULL));
 }
 
 /* This is the server process request loop. The server process loop
@@ -365,14 +361,13 @@ rx_ServerProc(void * unused)
     while (1) {
        sock = OSI_NULLSOCKET;
        rxi_ServerProc(threadID, newcall, &sock);
-       /* assert(sock != OSI_NULLSOCKET); */
+       /* osi_Assert(sock != OSI_NULLSOCKET); */
        newcall = NULL;
        rxi_ListenerProc(rfds, &threadID, &newcall);
-       /* assert(threadID != -1); */
-       /* assert(newcall != NULL); */
+       /* osi_Assert(threadID != -1); */
+       /* osi_Assert(newcall != NULL); */
     }
-    /* not reached */
-    return NULL;
+    AFS_UNREACHED(return(NULL));
 }
 
 /*
@@ -415,11 +410,14 @@ rxi_Listen(osi_socket sock)
 int
 rxi_Recvmsg(osi_socket socket, struct msghdr *msg_p, int flags)
 {
-#if defined(HAVE_LINUX_ERRQUEUE_H) && defined(ADAPT_PMTU)
-    while((rxi_HandleSocketError(socket)) > 0)
-       ;
-#endif
-    return recvmsg(socket, msg_p, flags);
+    int code;
+    code = recvmsg(socket, msg_p, flags);
+
+    if (code < 0) {
+       rxi_HandleSocketErrors(socket);
+    }
+
+    return code;
 }
 
 /*
@@ -429,52 +427,66 @@ rxi_Recvmsg(osi_socket socket, struct msghdr *msg_p, int flags)
 int
 rxi_Sendmsg(osi_socket socket, struct msghdr *msg_p, int flags)
 {
+    int err = 0;
     fd_set *sfds = (fd_set *) 0;
     while (sendmsg(socket, msg_p, flags) == -1) {
-       int err;
-       rx_stats.sendSelects++;
+
+#ifdef AFS_NT40_ENV
+       err = WSAGetLastError();
+#else
+       err = errno;
+#endif
+
+       if (rx_stats_active)
+           rx_atomic_inc(&rx_stats.sendSelects);
 
        if (!sfds) {
            if (!(sfds = IOMGR_AllocFDSet())) {
                (osi_Msg "rx failed to alloc fd_set: ");
                perror("rx_sendmsg");
-               return -1;
+               err = ENOMEM;
+               goto error;
            }
            FD_SET(socket, sfds);
        }
-#if defined(HAVE_LINUX_ERRQUEUE_H) && defined(ADAPT_PMTU)
-       while((rxi_HandleSocketError(socket)) > 0)
-         ;
-#endif
 #ifdef AFS_NT40_ENV
-       if (WSAGetLastError())
+       if (err)
 #elif defined(AFS_LINUX22_ENV)
        /* linux unfortunately returns ECONNREFUSED if the target port
         * is no longer in use */
        /* and EAGAIN if a UDP checksum is incorrect */
-       if (errno != EWOULDBLOCK && errno != ENOBUFS && errno != ECONNREFUSED
-           && errno != EAGAIN)
+       if (err != EWOULDBLOCK && err != ENOBUFS && err != ECONNREFUSED
+           && err != EAGAIN)
 #else
-       if (errno != EWOULDBLOCK && errno != ENOBUFS)
+       if (err != EWOULDBLOCK && err != ENOBUFS)
 #endif
        {
            (osi_Msg "rx failed to send packet: ");
            perror("rx_sendmsg");
-#ifndef AFS_NT40_ENV
-            if (errno > 0)
-              return -errno;
-#elif
-            if (WSAGetLastError() > 0)
-              return -WSAGetLastError();
-#endif
-           return -1;
+           goto error;
        }
-       while ((err = select(socket + 1, 0, sfds, 0, 0)) != 1) {
+       while ((err = select(
+#ifdef AFS_NT40_ENV
+                             0,
+#else
+                             socket + 1,
+#endif
+                             0, sfds, 0, 0)) != 1) {
            if (err >= 0 || errno != EINTR)
                osi_Panic("rxi_sendmsg: select error %d.%d", err, errno);
+           FD_ZERO(sfds);
+           FD_SET(socket, sfds);
        }
     }
     if (sfds)
        IOMGR_FreeFDSet(sfds);
     return 0;
+
+ error:
+    if (sfds)
+       IOMGR_FreeFDSet(sfds);
+    if (err > 0)
+       return -err;
+    return -1;
 }
+#endif