From owner-freebsd-bugs Wed Jan 9 0:41: 7 2002 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id CB21E37B402 for ; Wed, 9 Jan 2002 00:40:05 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id g098e5u13512; Wed, 9 Jan 2002 00:40:05 -0800 (PST) (envelope-from gnats) Received: from smtp02.mrf.mail.rcn.net (smtp02.mrf.mail.rcn.net [207.172.4.61]) by hub.freebsd.org (Postfix) with ESMTP id 274C837B416 for ; Wed, 9 Jan 2002 00:38:55 -0800 (PST) Received: from 209-122-220-227.s227.tnt6.nywnj.ny.dialup.rcn.com ([209.122.220.227] helo=unknown.whichever.org) by smtp02.mrf.mail.rcn.net with esmtp (Exim 3.33 #10) id 16OEG4-0002il-00 for FreeBSD-gnats-submit@freebsd.org; Wed, 09 Jan 2002 03:38:53 -0500 Received: (from archer@localhost) by unknown.whichever.org (8.11.6/8.11.6) id g098cp803252; Wed, 9 Jan 2002 03:38:51 -0500 (EST) (envelope-from archer) Message-Id: <200201090838.g098cp803252@unknown.whichever.org> Date: Wed, 9 Jan 2002 03:38:51 -0500 (EST) From: "Alexander Litvin"@FreeBSD.ORG, archer@whichever.org Reply-To: archer@whichever.org To: FreeBSD-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: 3.113 Subject: misc/33723: select(2) implementation in threaded (-lc_r) library is incorrect Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >Number: 33723 >Category: misc >Synopsis: select(2) implementation in threaded (-lc_r) library is incorrect >Confidential: no >Severity: serious >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Jan 09 00:40:05 PST 2002 >Closed-Date: >Last-Modified: >Originator: Alexander Litvin >Release: FreeBSD 5.0-CURRENT i386 >Organization: unknown >Environment: FreeBSD unknown.whichever.org 5.0-CURRENT FreeBSD 5.0-CURRENT #6: Mon Dec 31 16:05:29 EST 2001 root@unknown.whichever.org:/var/src/sys/i386/compile/UNKNOWN i386 System: FreeBSD 5.0-CURRENT (as of Dec 21, 2001) i386 CPU: Pentium/P54C (119.75-MHz 586-class CPU) Origin = "GenuineIntel" Id = 0x526 Stepping = 6 Features=0x1bf real memory = 33554432 (32768K bytes) avail memory = 29343744 (28656K bytes) >Description: The select(2) in case of libc_r is implemented via poll(2). The implementation is incorrect in two ways: 1. The current implementation returns the number of file descriptors for which there were observed events. So, if the same file descriptor bit is set in different fd_set's when select() is called, it will be counted only once. But select() is supposed to return total number of bits set in all fd_set's. 2. Current implementation checks the result of poll() for POLLNVAL, POLLHUP, POLLERR, POLLRDBAND and POLLPRI events set, and treats those as exceptional condition pending for the socket. But in terms of select(2), the only exceptional condition is OOB data being available for read. That is, POLLRDBAND and POLLPRI are ok, POLLNVAL should be treated as select(2) error (EBADF set in errno, and -1 returned). I'm not sure about POLLHUP and POLLERR -- may be, their place is among read events. >How-To-Repeat: Simple program to demonstrate is below. It indicates select() failure, when compiled without -lc_r, and select() succeds in threaded case. --------------------------------------------- #include #include #include #include int main() { fd_set fdset; struct timeval timeout; timeout.tv_sec = 60; timeout.tv_usec = 0; FD_ZERO(&fdset); FD_SET(10, &fdset); if (-1 == select(11,&fdset,NULL,NULL,&timeout)) perror("select fails "); else printf("select successful\n"); } --------------------------------------------- >Fix: The patch is below: -------------------- *** src/lib/libc_r/uthread/uthread_select.c.orig Wed Jan 9 02:46:17 2002 --- src/lib/libc_r/uthread/uthread_select.c Wed Jan 9 02:57:16 2002 *************** *** 52,58 **** struct pthread *curthread = _get_curthread(); struct timespec ts; int i, ret = 0, f_wait = 1; ! int pfd_index, got_one = 0, fd_count = 0; struct pthread_poll_data data; if (numfds > _thread_dtablesize) { --- 52,58 ---- struct pthread *curthread = _get_curthread(); struct timespec ts; int i, ret = 0, f_wait = 1; ! int pfd_index, got_events = 0, fd_count = 0; struct pthread_poll_data data; if (numfds > _thread_dtablesize) { *************** *** 166,177 **** * this file descriptor from the fdset if * the requested event wasn't ready. */ ! got_one = 0; if (readfds != NULL) { if (FD_ISSET(data.fds[i].fd, readfds)) { if (data.fds[i].revents & (POLLIN | POLLRDNORM)) ! got_one = 1; else FD_CLR(data.fds[i].fd, readfds); } --- 166,187 ---- * this file descriptor from the fdset if * the requested event wasn't ready. */ ! ! /* ! * First check for invalid descriptor. ! * If found, set errno and return -1 ! */ ! if (data.fds[i].revents & POLLNVAL) { ! errno = EBADF; ! return -1; ! } ! ! got_events = 0; if (readfds != NULL) { if (FD_ISSET(data.fds[i].fd, readfds)) { if (data.fds[i].revents & (POLLIN | POLLRDNORM)) ! got_events++; else FD_CLR(data.fds[i].fd, readfds); } *************** *** 180,186 **** if (FD_ISSET(data.fds[i].fd, writefds)) { if (data.fds[i].revents & (POLLOUT | POLLWRNORM | POLLWRBAND)) ! got_one = 1; else FD_CLR(data.fds[i].fd, writefds); --- 190,196 ---- if (FD_ISSET(data.fds[i].fd, writefds)) { if (data.fds[i].revents & (POLLOUT | POLLWRNORM | POLLWRBAND)) ! got_events++; else FD_CLR(data.fds[i].fd, writefds); *************** *** 189,204 **** if (exceptfds != NULL) { if (FD_ISSET(data.fds[i].fd, exceptfds)) { if (data.fds[i].revents & (POLLRDBAND | ! POLLPRI | POLLHUP | POLLERR | ! POLLNVAL)) ! got_one = 1; else FD_CLR(data.fds[i].fd, exceptfds); } } ! if (got_one) ! numfds++; } ret = numfds; } --- 199,213 ---- if (exceptfds != NULL) { if (FD_ISSET(data.fds[i].fd, exceptfds)) { if (data.fds[i].revents & (POLLRDBAND | ! POLLPRI)) ! got_events++; else FD_CLR(data.fds[i].fd, exceptfds); } } ! if (got_events) ! numfds+=got_events; } ret = numfds; } >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message