Date: Tue, 20 Aug 2013 04:31:14 GMT From: Vitja Makarov <vitja.makarov@gmail.com> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/181416: socket timeout rounding issue Message-ID: <201308200431.r7K4VECF003700@oldred.freebsd.org> Resent-Message-ID: <201308200440.r7K4e05H023450@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 181416 >Category: kern >Synopsis: socket timeout rounding issue >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Aug 20 04:40:00 UTC 2013 >Closed-Date: >Last-Modified: >Originator: Vitja Makarov >Release: 9.1-RELEASE >Organization: Rambler >Environment: FreeBSD dbg 9.1-RELEASE FreeBSD 9.1-RELEASE #5: Tue Aug 20 08:14:54 MSK 2013 root@dbg:/usr/obj/nfs/usr/src/sys/MYKERNEL i386 >Description: Recently I was playing with small socket timeouts. setsockopt(2) SO_RCVTIMEO and found a problem with it: if timeout is small enough read(2) may return before timeout is actually expired. I was unable to reproduce this on linux box. I found that kernel uses a timer with 1/HZ precision so it converts time in microseconds to ticks that's ok linux does it as well. The problem is in details: freebsd uses floor() approach while linux uses ceil(): from FreeBSD's sys/kern/uipc_socket.c: val = (u_long)(tv.tv_sec * hz) + tv.tv_usec / tick; if (val == 0 && tv.tv_usec != 0) val = 1; /* at least one tick if tv > 0 */ from Linux's net/core/sock.c: *timeo_p = tv.tv_sec*HZ + (tv.tv_usec+(1000000/HZ-1))/(1000000/HZ); So, for instance, we have a freebsd system running with kern.hz set to 100 and set receive timeout to 25ms that is converted to 2 ticks which is 20ms. In my test program read(2) returns with EAGAIN set in 0.019ms. >How-To-Repeat: >Fix: >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308200431.r7K4VECF003700>