kern/143029: poll() can return too large a number
John Plevyak
jplevyak at apache.org
Wed Jan 20 19:20:08 UTC 2010
>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 at 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:
More information about the freebsd-bugs
mailing list