Date: Wed, 20 Jan 2010 19:16:05 GMT From: John Plevyak <jplevyak@apache.org> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/143029: poll() can return too large a number Message-ID: <201001201916.o0KJG55D086537@www.freebsd.org> Resent-Message-ID: <201001201920.o0KJK8ev093421@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 143029 >Category: kern >Synopsis: poll() can return too large a number >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Jan 20 19:20:08 UTC 2010 >Closed-Date: >Last-Modified: >Originator: John Plevyak >Release: 8.0-RELEASE >Organization: Apache.org >Environment: FreeBSD jplevyak2.hsd1.ca.comcast.net. 8.0-RELEASE FreeBSD 8.0-RELEASE #0: Sat Nov 21 15:02:08 UTC 2009 root@mason.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64 >Description: I am calling poll() and the result is 2 while only one of the revent fields is non-zero. This is inside of libev where it results in a SEGV. I have talked to the libev maintainers who suggested that I talk to you. This is on FreeBSD 8. Inspection of the code in sys_generic.c and uipc_socket.c indicates that selrecord is being called twice for poll sockets and that pollrescan is counting the number of td->td_sel entries which are ready and returning the result. I am concerned that there are 2 entries for the poll socket because of the comments in selsetbits (sys_generic.c) which are: * XXX Check for a duplicate set. This can occur because a * socket calls selrecord() twice for each poll() call * resulting in two selfds per real fd. selrescan() will * call selsetbits twice as a result. This check is not being done for poll(). >How-To-Repeat: Simple tests do not show the problem since the pollscan() does not have the problem so if it returns a result the problem is not evident. I can reproduce in the context of the apache.org trafficserver linked with libev. I can provide build and setup instructions or a login to a VM with the required setup. >Fix: selsetbits uses the conditional: /* * XXX Check for a duplicate set. This can occur because a * socket calls selrecord() twice for each poll() call * resulting in two selfds per real fd. selrescan() will * call selsetbits twice as a result. */ if ((obits[msk][idx] & bit) != 0) continue; however looking at the code I think perhaps changing pollrescan to: /* * Note: backend also returns POLLHUP and * POLLERR if appropriate. */ int old_revents = fd->revents; fd->revents = fo_poll(fp, fd->events, td->td_ucred, td); if (!old_revents && fd->revents != 0) n++; or something similar might fix the problem. >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001201916.o0KJG55D086537>