Re: [Bug 3610] New: kernel-2.6.9 breaks Amanda
From: Stephen Hemminger <hidden>
Date: 2004-10-26 17:54:22
Try the following patch to amanda that resolves potential issues with UDP and blocking receive.
--- amanda-2.4.4p3/common-src/dgram.c.orig 2004-10-26 09:51:27.000000000 -0700
+++ amanda-2.4.4p3/common-src/dgram.c 2004-10-26 10:01:56.622775784 -0700@@ -248,9 +248,31 @@ socklen_t addrlen; int nfound; int save_errno; + int flags; sock = dgram->socket; + /* Need to be in non-blocking mode before doing receive, + * because select on Linux will return true when there is + * a UDP message with checksum error, but receive will + * then hang. + */ + flags = fcntl(sock, F_GETFL); + if (flags < 0) { + save_errno = errno; + dbprintf(("%s: dgram_recv: fcntl get flags failed %s\n", + debug_prefix(NULL), strerror(save_errno))); + return -1; + } + + if(fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0) { + save_errno = errno; + dbprintf(("%s: dgram_recv: fcntl set flags failed %s\n", + debug_prefix(NULL), strerror(save_errno))); + return -1; + } + + retry: FD_ZERO(&ready); FD_SET(sock, &ready); to.tv_sec = timeout;
@@ -284,6 +306,7 @@ nfound = -1; } errno = save_errno; + fcntl(sock, F_SETFL, flags); return nfound; }
@@ -291,13 +314,19 @@ size = recvfrom(sock, dgram->data, MAX_DGRAM, 0, (struct sockaddr *)fromaddr, &addrlen); if(size == -1) { + if (errno == EINTR || errno == EAGAIN) + goto retry; save_errno = errno; dbprintf(("%s: dgram_recv: recvfrom() failed: %s\n", debug_prefix(NULL), strerror(save_errno))); errno = save_errno; + fcntl(sock, F_SETFL, flags); return -1; } + + fcntl(sock, F_SETFL, flags); + dgram->len = size; dgram->data[size] = '\0'; dgram->cur = dgram->data;