diff --git a/man2/select_tut.2 b/man2/select_tut.2 index 83f0ef2d1..d8c5585a4 100644 --- a/man2/select_tut.2 +++ b/man2/select_tut.2 @@ -342,7 +342,162 @@ A simple example of the use of can be found in the .BR select (2) manual page. -.SH PORT FORWARDING EXAMPLE +.SS Select Law +Many people who try to use +.BR select () +come across behavior that is +difficult to understand and produces non-portable or borderline +results. +For instance, the above program is carefully written not to +block at any point, even though it does not set its file descriptors to +non-blocking mode at all (see +.BR ioctl (2)). +It is easy to introduce +subtle errors that will remove the advantage of using +.BR select (), +hence I will present a list of essentials to watch for when using the +.BR select () +call. +.TP +\fB1.\fP +You should always try to use +.BR select () +without a timeout. +Your program +should have nothing to do if there is no data available. +Code that +depends on timeouts is not usually portable and is difficult to debug. +.TP +\fB2.\fP +The value \fInfds\fP must be properly calculated for efficiency as +explained above. +.TP +\fB3.\fP +No file descriptor must be added to any set if you do not intend +to check its result after the +.BR select () +call, and respond +appropriately. +See next rule. +.TP +\fB4.\fP +After +.BR select () +returns, all file descriptors in all sets +should be checked to see if they are ready. +.\" mtk, May 2006: the following isn't really true. +.\" Any file descriptor that is available +.\" for writing \fImust\fP be written to, and any file descriptor +.\" available for reading \fImust\fP be read, etc. +.TP +\fB5.\fP +The functions +.BR read (2), +.BR recv (2), +.BR write (2), +and +.BR send (2) +do \fInot\fP necessarily read/write the full amount of data +that you have requested. +If they do read/write the full amount, its +because you have a low traffic load and a fast stream. +This is not +always going to be the case. +You should cope with the case of your +functions only managing to send or receive a single byte. +.TP +\fB6.\fP +Never read/write only in single bytes at a time unless your are really +sure that you have a small amount of data to process. +It is extremely +inefficient not to read/write as much data as you can buffer each time. +The buffers in the example above are 1024 bytes although they could +easily be made larger. +.TP +\fB7.\fP +The functions +.BR read (2), +.BR recv (2), +.BR write (2), +and +.BR send (2) +as well as the +.BR select () +call can return \-1 with +.I errno +set to \fBEINTR\fP, +or with +.I errno +set to \fBEAGAIN\fP (\fBEWOULDBLOCK\fP). +These results must be properly managed (not done properly +above). +If your program is not going to receive any signals then +it is unlikely you will get \fBEINTR\fP. +If your program does not +set non-blocking I/O, you will not get \fBEAGAIN\fP. +Nonetheless +you should still cope with these errors for completeness. +.TP +\fB8.\fP +Never call +.BR read (2), +.BR recv (2), +.BR write (2), +or +.BR send (2) +with a buffer length of zero. +.TP +\fB9.\fP +If the functions +.BR read (2), +.BR recv (2), +.BR write (2), +and +.BR send (2) +fail +with errors other than those listed in \fB7.\fP, +or one of the input functions returns 0, indicating end of file, +then you should \fInot\fP pass that descriptor to +.BR select () +again. +In the above example, +I close the descriptor immediately, and then set it to \-1 +to prevent it being included in a set. +.TP +\fB10.\fP +The timeout value must be initialized with each new call to +.BR select (), +since some operating systems modify the structure. +.BR pselect () +however does not modify its timeout structure. +.TP +\fB11.\fP +I have heard that the Windows socket layer does not cope with OOB data +properly. +It also does not cope with +.BR select () +calls when no file +descriptors are set at all. +Having no file descriptors set is a useful +way to sleep the process with sub-second precision by using the timeout. +(See further on.) +.SS Usleep Emulation +On systems that do not have a +.BR usleep (3) +function, you can call +.BR select () +with a finite timeout and no file descriptors as +follows: +.PP +.nf + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 200000; /* 0.2 seconds */ + select(0, NULL, NULL, NULL, &tv); +.fi +.PP +This is only guaranteed to work on Unix systems, however. +.SH EXAMPLE Here is an example that better demonstrates the true utility of .BR select (). The listing below is a TCP forwarding program that forwards @@ -633,161 +788,6 @@ time, although it could easily be extended to do this with a linked list of buffers \(em one for each connection. At the moment, new connections cause the current connection to be dropped. -.SS Select Law -Many people who try to use -.BR select () -come across behavior that is -difficult to understand and produces non-portable or borderline -results. -For instance, the above program is carefully written not to -block at any point, even though it does not set its file descriptors to -non-blocking mode at all (see -.BR ioctl (2)). -It is easy to introduce -subtle errors that will remove the advantage of using -.BR select (), -hence I will present a list of essentials to watch for when using the -.BR select () -call. -.TP -\fB1.\fP -You should always try to use -.BR select () -without a timeout. -Your program -should have nothing to do if there is no data available. -Code that -depends on timeouts is not usually portable and is difficult to debug. -.TP -\fB2.\fP -The value \fInfds\fP must be properly calculated for efficiency as -explained above. -.TP -\fB3.\fP -No file descriptor must be added to any set if you do not intend -to check its result after the -.BR select () -call, and respond -appropriately. -See next rule. -.TP -\fB4.\fP -After -.BR select () -returns, all file descriptors in all sets -should be checked to see if they are ready. -.\" mtk, May 2006: the following isn't really true. -.\" Any file descriptor that is available -.\" for writing \fImust\fP be written to, and any file descriptor -.\" available for reading \fImust\fP be read, etc. -.TP -\fB5.\fP -The functions -.BR read (2), -.BR recv (2), -.BR write (2), -and -.BR send (2) -do \fInot\fP necessarily read/write the full amount of data -that you have requested. -If they do read/write the full amount, its -because you have a low traffic load and a fast stream. -This is not -always going to be the case. -You should cope with the case of your -functions only managing to send or receive a single byte. -.TP -\fB6.\fP -Never read/write only in single bytes at a time unless your are really -sure that you have a small amount of data to process. -It is extremely -inefficient not to read/write as much data as you can buffer each time. -The buffers in the example above are 1024 bytes although they could -easily be made larger. -.TP -\fB7.\fP -The functions -.BR read (2), -.BR recv (2), -.BR write (2), -and -.BR send (2) -as well as the -.BR select () -call can return \-1 with -.I errno -set to \fBEINTR\fP, -or with -.I errno -set to \fBEAGAIN\fP (\fBEWOULDBLOCK\fP). -These results must be properly managed (not done properly -above). -If your program is not going to receive any signals then -it is unlikely you will get \fBEINTR\fP. -If your program does not -set non-blocking I/O, you will not get \fBEAGAIN\fP. -Nonetheless -you should still cope with these errors for completeness. -.TP -\fB8.\fP -Never call -.BR read (2), -.BR recv (2), -.BR write (2), -or -.BR send (2) -with a buffer length of zero. -.TP -\fB9.\fP -If the functions -.BR read (2), -.BR recv (2), -.BR write (2), -and -.BR send (2) -fail -with errors other than those listed in \fB7.\fP, -or one of the input functions returns 0, indicating end of file, -then you should \fInot\fP pass that descriptor to -.BR select () -again. -In the above example, -I close the descriptor immediately, and then set it to \-1 -to prevent it being included in a set. -.TP -\fB10.\fP -The timeout value must be initialized with each new call to -.BR select (), -since some operating systems modify the structure. -.BR pselect () -however does not modify its timeout structure. -.TP -\fB11.\fP -I have heard that the Windows socket layer does not cope with OOB data -properly. -It also does not cope with -.BR select () -calls when no file -descriptors are set at all. -Having no file descriptors set is a useful -way to sleep the process with sub-second precision by using the timeout. -(See further on.) -.SS Usleep Emulation -On systems that do not have a -.BR usleep (3) -function, you can call -.BR select () -with a finite timeout and no file descriptors as -follows: -.PP -.nf - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 200000; /* 0.2 seconds */ - select(0, NULL, NULL, NULL, &tv); -.fi -.PP -This is only guaranteed to work on Unix systems, however. .SH RETURN VALUE On success, .BR select ()