This patch imports the unmodified current version of NetBSD libc. The NetBSD includes are in /nbsd_include, while the libc code itself is split between lib/nbsd_libc and common/lib/libc.
		
			
				
	
	
		
			354 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Groff
		
	
	
	
	
	
			
		
		
	
	
			354 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Groff
		
	
	
	
	
	
.\"	$NetBSD: select.2,v 1.38 2010/04/05 21:25:56 joerg Exp $
 | 
						|
.\"
 | 
						|
.\" Copyright (c) 1983, 1991, 1993
 | 
						|
.\"	The Regents of the University of California.  All rights reserved.
 | 
						|
.\"
 | 
						|
.\" Redistribution and use in source and binary forms, with or without
 | 
						|
.\" modification, are permitted provided that the following conditions
 | 
						|
.\" are met:
 | 
						|
.\" 1. Redistributions of source code must retain the above copyright
 | 
						|
.\"    notice, this list of conditions and the following disclaimer.
 | 
						|
.\" 2. Redistributions in binary form must reproduce the above copyright
 | 
						|
.\"    notice, this list of conditions and the following disclaimer in the
 | 
						|
.\"    documentation and/or other materials provided with the distribution.
 | 
						|
.\" 3. Neither the name of the University nor the names of its contributors
 | 
						|
.\"    may be used to endorse or promote products derived from this software
 | 
						|
.\"    without specific prior written permission.
 | 
						|
.\"
 | 
						|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | 
						|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
						|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
						|
.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | 
						|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
						|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
						|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
						|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
						|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
						|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
						|
.\" SUCH DAMAGE.
 | 
						|
.\"
 | 
						|
.\"     @(#)select.2	8.2 (Berkeley) 3/25/94
 | 
						|
.\"
 | 
						|
.Dd October 18, 2008
 | 
						|
.Dt SELECT 2
 | 
						|
.Os
 | 
						|
.Sh NAME
 | 
						|
.Nm select ,
 | 
						|
.Nm pselect
 | 
						|
.Nd synchronous I/O multiplexing
 | 
						|
.Sh LIBRARY
 | 
						|
.Lb libc
 | 
						|
.Sh SYNOPSIS
 | 
						|
.In sys/select.h
 | 
						|
.Ft int
 | 
						|
.Fn select "int nfds" "fd_set * restrict readfds" "fd_set * restrict writefds" "fd_set * restrict exceptfds" "struct timeval * restrict timeout"
 | 
						|
.Ft int
 | 
						|
.Fn pselect "int nfds" "fd_set * restrict readfds" "fd_set * restrict writefds" "fd_set * restrict exceptfds" "const struct timespec *restrict timeout" "const sigset_t * restrict sigmask"
 | 
						|
.Fn FD_SET "int fd" "fd_set *fdset"
 | 
						|
.Fn FD_CLR "int fd" "fd_set *fdset"
 | 
						|
.Fn FD_ISSET "int fd" "fd_set *fdset"
 | 
						|
.Fn FD_ZERO "fd_set *fdset"
 | 
						|
.Sh DESCRIPTION
 | 
						|
.Fn select
 | 
						|
and
 | 
						|
.Fn pselect
 | 
						|
examine the I/O descriptor sets whose addresses are passed in
 | 
						|
.Fa readfds ,
 | 
						|
.Fa writefds ,
 | 
						|
and
 | 
						|
.Fa exceptfds
 | 
						|
to see if some of their descriptors
 | 
						|
are ready for reading, are ready for writing, or have an exceptional
 | 
						|
condition pending, respectively.
 | 
						|
The first
 | 
						|
.Fa nfds
 | 
						|
descriptors are checked in each set;
 | 
						|
i.e., the descriptors from 0 through
 | 
						|
.Fa nfds Ns No \-1
 | 
						|
in the descriptor sets are examined.
 | 
						|
This means that
 | 
						|
.Fa nfds
 | 
						|
must be set to the highest file descriptor of the three sets, plus one.
 | 
						|
On return,
 | 
						|
.Fn select
 | 
						|
and
 | 
						|
.Fn pselect
 | 
						|
replace the given descriptor sets
 | 
						|
with subsets consisting of those descriptors that are ready
 | 
						|
for the requested operation.
 | 
						|
.Fn select
 | 
						|
and
 | 
						|
.Fn pselect
 | 
						|
return the total number of ready descriptors in all the sets.
 | 
						|
.Pp
 | 
						|
The descriptor sets are stored as bit fields in arrays of integers.
 | 
						|
The following macros are provided for manipulating such descriptor sets:
 | 
						|
.Fn FD_ZERO fdset
 | 
						|
initializes a descriptor set pointed to by
 | 
						|
.Fa fdset
 | 
						|
to the null set.
 | 
						|
.Fn FD_SET fd fdset
 | 
						|
includes a particular descriptor
 | 
						|
.Fa fd
 | 
						|
in
 | 
						|
.Fa fdset .
 | 
						|
.Fn FD_CLR fd fdset
 | 
						|
removes
 | 
						|
.Fa fd
 | 
						|
from
 | 
						|
.Fa fdset .
 | 
						|
.Fn FD_ISSET fd fdset
 | 
						|
is non-zero if
 | 
						|
.Fa fd
 | 
						|
is a member of
 | 
						|
.Fa fdset ,
 | 
						|
zero otherwise.
 | 
						|
The behavior of these macros is undefined if
 | 
						|
a descriptor value is less than zero or greater than or equal to
 | 
						|
.Dv FD_SETSIZE ,
 | 
						|
which is normally at least equal
 | 
						|
to the maximum number of descriptors supported by the system.
 | 
						|
.Pp
 | 
						|
If
 | 
						|
.Fa timeout
 | 
						|
is a non-null pointer, it specifies a maximum interval to wait for the
 | 
						|
selection to complete.
 | 
						|
If
 | 
						|
.Fa timeout
 | 
						|
is a null pointer, the select blocks indefinitely.
 | 
						|
To poll without blocking, the
 | 
						|
.Fa timeout
 | 
						|
argument should be non-null, pointing to a zero-valued timeval or timespec
 | 
						|
structure, as appropriate.
 | 
						|
.Fa timeout
 | 
						|
is not changed by
 | 
						|
.Fn select ,
 | 
						|
and may be reused on subsequent calls; however, it is good style to
 | 
						|
re-initialize it before each invocation of
 | 
						|
.Fn select .
 | 
						|
.Pp
 | 
						|
If
 | 
						|
.Fa sigmask
 | 
						|
is a non-null pointer, then the
 | 
						|
.Fn pselect
 | 
						|
function shall replace the signal mask of the caller by the set of
 | 
						|
signals pointed to by
 | 
						|
.Fa sigmask
 | 
						|
before examining the descriptors, and shall restore the signal mask
 | 
						|
of the calling thread before returning.
 | 
						|
.Pp
 | 
						|
Any of
 | 
						|
.Fa readfds ,
 | 
						|
.Fa writefds ,
 | 
						|
and
 | 
						|
.Fa exceptfds
 | 
						|
may be given as null pointers if no descriptors are of interest.
 | 
						|
.Sh NOTES
 | 
						|
It is recommended to use the
 | 
						|
.Xr poll 2
 | 
						|
interface instead, which tends to be more portable and efficient.
 | 
						|
.Sh RETURN VALUES
 | 
						|
.Fn select
 | 
						|
returns the number of ready descriptors that are contained in
 | 
						|
the descriptor sets,
 | 
						|
or \-1 if an error occurred.
 | 
						|
If the time limit expires,
 | 
						|
.Fn select
 | 
						|
returns 0.
 | 
						|
If
 | 
						|
.Fn select
 | 
						|
returns with an error,
 | 
						|
including one due to an interrupted call,
 | 
						|
the descriptor sets will be unmodified.
 | 
						|
.Sh EXAMPLES
 | 
						|
.Bd -literal
 | 
						|
#include \*[Lt]stdio.h\*[Gt]
 | 
						|
#include \*[Lt]stdlib.h\*[Gt]
 | 
						|
#include \*[Lt]unistd.h\*[Gt]
 | 
						|
#include \*[Lt]string.h\*[Gt]
 | 
						|
#include \*[Lt]err.h\*[Gt]
 | 
						|
#include \*[Lt]errno.h\*[Gt]
 | 
						|
#include \*[Lt]sys/types.h\*[Gt]
 | 
						|
#include \*[Lt]sys/time.h\*[Gt]
 | 
						|
 | 
						|
int
 | 
						|
main(int argc, char **argv)
 | 
						|
{
 | 
						|
	fd_set read_set;
 | 
						|
	struct timeval timeout;
 | 
						|
	int ret, fd, i;
 | 
						|
 | 
						|
	/* file descriptor 1 is stdout */
 | 
						|
	fd = 1;
 | 
						|
 | 
						|
	/* Wait for ten seconds. */
 | 
						|
	timeout.tv_sec = 10;
 | 
						|
	timeout.tv_usec = 0;
 | 
						|
 | 
						|
	/* Initialize the read set to null */
 | 
						|
	FD_ZERO(\*[Am]read_set);
 | 
						|
 | 
						|
	/* Add file descriptor 1 to read_set */
 | 
						|
	FD_SET(fd, \*[Am]read_set);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Check if data is ready to be readen on
 | 
						|
	 * file descriptor 1, give up after 10 seconds.
 | 
						|
	 */
 | 
						|
	ret = select(fd + 1, \*[Am]read_set, NULL, NULL, \*[Am]timeout);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Returned value is the number of file
 | 
						|
	 * descriptors ready for I/O, or -1 on error.
 | 
						|
	 */
 | 
						|
	switch (ret) {
 | 
						|
	case \-1:
 | 
						|
		err(EXIT_FAILURE, "select() failed");
 | 
						|
		break;
 | 
						|
 | 
						|
	case 0:
 | 
						|
		printf("Timeout, no data received.\en");
 | 
						|
		break;
 | 
						|
 | 
						|
	default:
 | 
						|
		printf("Data received on %d file desciptor(s)\en", ret);
 | 
						|
 | 
						|
		/*
 | 
						|
		 * select(2) hands back a file descriptor set where
 | 
						|
		 * only descriptors ready for I/O are set. These can
 | 
						|
		 * be tested using FD_ISSET
 | 
						|
		 */
 | 
						|
		for (i = 0; i \*[Lt]= fd; i++) {
 | 
						|
			if (FD_ISSET(i, \*[Am]read_set)) {
 | 
						|
				printf("Data on file descriptor %d\en", i);
 | 
						|
				/* Remove the file descriptor from the set */
 | 
						|
				FD_CLR(fd, \*[Am]read_set);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
.Ed
 | 
						|
.Sh ERRORS
 | 
						|
An error return from
 | 
						|
.Fn select
 | 
						|
indicates:
 | 
						|
.Bl -tag -width Er
 | 
						|
.It Bq Er EBADF
 | 
						|
One of the descriptor sets specified an invalid descriptor.
 | 
						|
.It Bq Er EFAULT
 | 
						|
One or more of
 | 
						|
.Fa readfds ,
 | 
						|
.Fa writefds ,
 | 
						|
or
 | 
						|
.Fa exceptfds
 | 
						|
points outside the process's allocated address space.
 | 
						|
.It Bq Er EINTR
 | 
						|
A signal was delivered before the time limit expired and
 | 
						|
before any of the selected events occurred.
 | 
						|
.It Bq Er EINVAL
 | 
						|
The specified time limit is invalid.
 | 
						|
One of its components is negative or too large.
 | 
						|
.El
 | 
						|
.Sh SEE ALSO
 | 
						|
.Xr accept 2 ,
 | 
						|
.Xr connect 2 ,
 | 
						|
.Xr gettimeofday 2 ,
 | 
						|
.Xr poll 2 ,
 | 
						|
.Xr read 2 ,
 | 
						|
.Xr recv 2 ,
 | 
						|
.Xr send 2 ,
 | 
						|
.Xr write 2 ,
 | 
						|
.Xr getdtablesize 3
 | 
						|
.Sh HISTORY
 | 
						|
The
 | 
						|
.Fn select
 | 
						|
function call appeared in
 | 
						|
.Bx 4.2 .
 | 
						|
.Sh BUGS
 | 
						|
Although the provision of
 | 
						|
.Xr getdtablesize 3
 | 
						|
was intended to allow user programs to be written independent
 | 
						|
of the kernel limit on the number of open files, the dimension
 | 
						|
of a sufficiently large bit field for select remains a problem.
 | 
						|
The default bit size of
 | 
						|
.Ft fd_set
 | 
						|
is based on the symbol
 | 
						|
.Dv FD_SETSIZE
 | 
						|
(currently 256),
 | 
						|
but that is somewhat smaller than the current kernel limit
 | 
						|
to the number of open files.
 | 
						|
However, in order to accommodate programs which might potentially
 | 
						|
use a larger number of open files with select, it is possible
 | 
						|
to increase this size within a program by providing
 | 
						|
a larger definition of
 | 
						|
.Dv FD_SETSIZE
 | 
						|
before the inclusion of
 | 
						|
.In sys/types.h .
 | 
						|
The kernel will cope, and the userland libraries provided with the
 | 
						|
system are also ready for large numbers of file descriptors.
 | 
						|
.Pp
 | 
						|
Note:
 | 
						|
.Xr rpc 3
 | 
						|
library uses
 | 
						|
.Ft fd_set
 | 
						|
with the default
 | 
						|
.Dv FD_SETSIZE
 | 
						|
as part of its ABI.
 | 
						|
Therefore, programs that use
 | 
						|
.Xr rpc 3
 | 
						|
routines cannot change
 | 
						|
.Dv FD_SETSIZE .
 | 
						|
.Pp
 | 
						|
Alternatively, to be really safe, it is possible to allocate
 | 
						|
.Ft fd_set
 | 
						|
bit-arrays dynamically.
 | 
						|
The idea is to permit a program to work properly even if it is
 | 
						|
.Xr execve 2 Ns 'd
 | 
						|
with 4000 file descriptors pre-allocated.
 | 
						|
The following illustrates the technique which is used by
 | 
						|
userland libraries:
 | 
						|
.Pp
 | 
						|
.Bd -literal -offset indent -compact
 | 
						|
	fd_set *fdsr;
 | 
						|
	int max = fd;
 | 
						|
 | 
						|
	fdsr = (fd_set *)calloc(howmany(max+1, NFDBITS),
 | 
						|
	    sizeof(fd_mask));
 | 
						|
	if (fdsr == NULL) {
 | 
						|
		...
 | 
						|
		return (-1);
 | 
						|
	}
 | 
						|
	FD_SET(fd, fdsr);
 | 
						|
	n = select(max+1, fdsr, NULL, NULL, \*[Am]tv);
 | 
						|
	...
 | 
						|
	free(fdsr);
 | 
						|
.Ed
 | 
						|
.Pp
 | 
						|
.Fn select
 | 
						|
should probably have been designed to return the time remaining from the
 | 
						|
original timeout, if any, by modifying the time value in place.
 | 
						|
Even though some systems stupidly act in this different way, it is
 | 
						|
unlikely this semantic will ever be commonly implemented, as the
 | 
						|
change causes massive source code compatibility problems.
 | 
						|
Furthermore, recent new standards have dictated the current behaviour.
 | 
						|
In general, due to the existence of those
 | 
						|
non-conforming systems, it is unwise to assume that the timeout
 | 
						|
value will be unmodified by the
 | 
						|
.Fn select
 | 
						|
call, and the caller should reinitialize it on each invocation.
 | 
						|
Calculating the delta is easily done by calling
 | 
						|
.Xr gettimeofday 2
 | 
						|
before and after the call to
 | 
						|
.Fn select ,
 | 
						|
and using
 | 
						|
.Fn timersub
 | 
						|
(as described in
 | 
						|
.Xr getitimer 2 ) .
 | 
						|
.Pp
 | 
						|
Internally to the kernel,
 | 
						|
.Fn select
 | 
						|
works poorly if multiple processes wait on the same file descriptor.
 |