vol: Add timeouts to SYNC server select() calls
authorAndrew Deason <adeason@sinenomine.net>
Tue, 29 Mar 2011 17:28:46 +0000 (12:28 -0500)
committerDerrick Brashear <shadow@dementia.org>
Wed, 30 Mar 2011 15:10:07 +0000 (08:10 -0700)
Normally *SYNC server processes wait indefinitely for activity to
occur on one of the SYNC sockets. On some Linux kernels, there exists
a race condition where data can come in on a socket, but the select()
call continues to wait. To ensure that we do not hang forever in such
a scenario, add a timeout to the select() call, which will ensure we
notice the new data within 10 seconds. Raise the timeout on non-Linux
to reduce impact elsewhere.

The Linux kernel bug is tracked in
<https://bugzilla.redhat.com/show_bug.cgi?id=494404>, though that bug
report may not represent all affected kernels.

Change-Id: I3250eb53d59610ccbcffe9e8e283984d5ae0e2b4
Reviewed-on: http://gerrit.openafs.org/4377
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>

src/vol/daemon_com.h
src/vol/fssync-server.c
src/vol/salvsync-server.c

index 81fd38c..249c270 100644 (file)
@@ -87,6 +87,15 @@ enum SYNCReasonCode {
     afs_int64 _##buf##_l[SYNC_PROTO_MAX_LEN/sizeof(afs_int64)]; \
     char * buf = (char *)(_##buf##_l)
 
+#ifdef AFS_LINUX26_ENV
+/* Some Linux kernels have a bug where we are not woken up immediately from a
+ * select() when data is available. Work around this by having a low select()
+ * timeout, so we don't hang in those situations. */
+# define SYNC_SELECT_TIMEOUT 10
+#else
+# define SYNC_SELECT_TIMEOUT 86400
+#endif
+
 #ifdef USE_UNIX_SOCKETS
 #include <afs/afsutil.h>
 #include <sys/un.h>
index 0d2aa7e..0b50bde 100644 (file)
@@ -310,12 +310,15 @@ FSYNC_sync(void * args)
            CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
 #else
        int maxfd;
+       struct timeval s_timeout;
        GetHandler(&FSYNC_readfds, &maxfd);
+       s_timeout.tv_sec = SYNC_SELECT_TIMEOUT;
+       s_timeout.tv_usec = 0;
        /* Note: check for >= 1 below is essential since IOMGR_select
         * doesn't have exactly same semantics as select.
         */
 #ifdef AFS_PTHREAD_ENV
-       if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
+       if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, &s_timeout) >= 1)
 #else /* AFS_PTHREAD_ENV */
        if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
 #endif /* AFS_PTHREAD_ENV */
index f6b530a..f054dd6 100644 (file)
@@ -342,11 +342,14 @@ SALVSYNC_syncThread(void * args)
 
     for (;;) {
        int maxfd;
+       struct timeval s_timeout;
        GetHandler(&SALVSYNC_readfds, &maxfd);
+       s_timeout.tv_sec = SYNC_SELECT_TIMEOUT;
+       s_timeout.tv_usec = 0;
        /* Note: check for >= 1 below is essential since IOMGR_select
         * doesn't have exactly same semantics as select.
         */
-       if (select(maxfd + 1, &SALVSYNC_readfds, NULL, NULL, NULL) >= 1)
+       if (select(maxfd + 1, &SALVSYNC_readfds, NULL, NULL, &s_timeout) >= 1)
            CallHandler(&SALVSYNC_readfds);
     }