Date: Fri, 14 Dec 2001 12:08:41 +0100 (CET) From: Hartmut Brandt <brandt@fokus.gmd.de> To: FreeBSD-gnats-submit@freebsd.org Subject: kern/32827: small SO_RCVTIMEO values are taken to be zero Message-ID: <200112141108.fBEB8fL69040@fokus.gmd.de>
next in thread | raw e-mail | index | archive | help
>Number: 32827 >Category: kern >Synopsis: small SO_RCVTIMEO values are taken to be zero >Confidential: no >Severity: serious >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Dec 14 03:10:01 PST 2001 >Closed-Date: >Last-Modified: >Originator: Hartmut Brandt >Release: FreeBSD 5.0-CURRENT i386 >Organization: FhG Fokus >Environment: System: FreeBSD beagle.fokus.gmd.de 5.0-CURRENT FreeBSD 5.0-CURRENT #3: Mon Dec 10 11:29:08 CET 2001 hbb@beagle.fokus.gmd.de:/opt/obj/usr/src/sys/BEAGLE i386 >Description: If the receive timeout of a socket is set to a number of microseconds larger than 0 but lesser than the value of 'tick', the code in uipc_socket.c /* assert(tick > 0); */ /* assert(ULONG_MAX - SHRT_MAX >= 1000000); */ 1250: val = (u_long)(tv.tv_sec * hz) + tv.tv_usec / tick; if (val > SHRT_MAX) { error = EDOM; goto bad; computes a timeout value for the socket of 0, causing subsequence receive operations to block as if no timeout had been specified. This is unexpected and not easily controllable by the application (one has to either fetch the value of tick via sysctl or always make a getsockopt after the setsockopt). Only timeout values with tv_sec==0 and tv_usec==0 should block indefinitely. >How-To-Repeat: Compile and run the following program and find it to timeout the first receive after 1 second and to block forever on thesecond receive (given no UDP packet is seen on 127.0.0.1:10000). # include <sys/types.h> # include <sys/socket.h> # include <sys/time.h> # include <stdio.h> # include <errno.h> # include <string.h> # include <err.h> # include <netinet/in.h> int main(int argc, char *argv[]) { int s; struct timeval tv; struct sockaddr_in sin; u_char buf[1000]; if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) err(1, "socket"); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_port = htons(10000); sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) err(1, "bind"); tv.tv_sec = 1; tv.tv_usec = 0; if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) err(1, "setsockopt"); printf("recv 1...\n"); if (recv(s, buf, sizeof(buf), 0) == -1) warn("recv"); tv.tv_sec = 0; tv.tv_usec = 100; if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) err(1, "setsockopt"); printf("recv 2...\n"); if (recv(s, buf, sizeof(buf), 0) == -1) warn("recv"); return (0); } >Fix: Apply the following patch to /usr/src/sys/kern/uipc_socket.c (this fixes the same problem for the send case): Index: uipc_socket.c =================================================================== RCS file: /usr/ncvs/src/sys/kern/uipc_socket.c,v retrieving revision 1.106 diff -r1.106 uipc_socket.c 1254a1255,1256 > if (val == 0 && (tv.tv_usec != 0 || tv.tv_sec != 0)) > val = 1; >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200112141108.fBEB8fL69040>