From owner-freebsd-bugs@FreeBSD.ORG Wed Jan 20 19:20:08 2010 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A4D1D1065672 for ; Wed, 20 Jan 2010 19:20:08 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 680178FC32 for ; Wed, 20 Jan 2010 19:20:08 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id o0KJK8Nw093422 for ; Wed, 20 Jan 2010 19:20:08 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id o0KJK8ev093421; Wed, 20 Jan 2010 19:20:08 GMT (envelope-from gnats) Resent-Date: Wed, 20 Jan 2010 19:20:08 GMT Resent-Message-Id: <201001201920.o0KJK8ev093421@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, John Plevyak Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 42AE1106568B for ; Wed, 20 Jan 2010 19:16:06 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 18D358FC18 for ; Wed, 20 Jan 2010 19:16:06 +0000 (UTC) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o0KJG5WK086538 for ; Wed, 20 Jan 2010 19:16:05 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id o0KJG55D086537; Wed, 20 Jan 2010 19:16:05 GMT (envelope-from nobody) Message-Id: <201001201916.o0KJG55D086537@www.freebsd.org> Date: Wed, 20 Jan 2010 19:16:05 GMT From: John Plevyak To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/143029: poll() can return too large a number X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Jan 2010 19:20:08 -0000 >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: