guy@uunet.uu.net (Guy Harris) (03/06/89)
>...it may well have *encouraged* the use of "getdtablesize()", which >is unfortunate. For more reasons than just "it causes your program not to work if your system is upgraded to support more than 64 file descriptors." Note that even if you *do* use "fd_set"s, 4.3BSD-style, if you are using no file descriptor larger than 31, you're causing the kernel to copy up to 3 32-bit words more than it has to if you use "getdtablesize()" as the argument. "getdtablesize()" in 4.3BSD, and in SunOS 4.0 and some other systems, returns 64, which tells the "select" code that it has to copy 64 bits, or 8 bytes, worth of "fd_set". If the largest file descriptor you use is 31 or less, the file descriptor set fits in 4 bytes, so the other 4 bytes are copied into and out of the kernel unnecessarily. Moral: don't use "getdtablesize()" in "select"; instead, figure out what the largest file descriptor number you're using is, and pass that number plus 1 as the first argument to "select".
guy@uunet.uu.net (Guy Harris) (03/24/89)
>In my experience, this assertion that using fd_sets will solve you >problems in the case of binary (cf source) compatability is incorrect. In my original posting, I described "improper" usage of "select" as: pass(ing) in pointers to "int"s rather than "fd_set"s, but pass(ing) the result of "getdtablesize()" as the first argument under the assumption that it will always return a number less than or equal to the number of bits in an "int" and also said: ...it (is) a bad idea to use "getdtablesize" - or, at least, to use it without cutting its value off at 32 - because the system might be changed to support more than (# of bits per "int") file descriptors... which was not all meant to "assert that using fd_sets will solve your problems in the case of binary compatibility". It was meant to assert that *not using 'getdtablesize()'*, but using, say, 32, would solve your problems. I should have made it clearer in the first paragraph that the fix to the problem mentioned therein was not simply to change the first part by passing in pointers to "fd_set"s. "properly" doesn't just mean "use 'fd_set's"; it means "don't pass the result of 'getdtablesize()' as the first argument unless you mean it" - i.e., don't pass the result of 'getdtablesize()' unless you're actually using file descriptor 'getdtablesize() - 1'. The proper way to use "select" - both for reasons of correctness *and* performance (see my second posting) - is to pass one greater than the highest file descriptor number you use as the first argument. Thus, most programs will probably pass a relatively small number - <= 32 - to "select" as the first argument.