| Summary: | FD_ISSET returns long, not int. | ||
|---|---|---|---|
| Product: | Base System | Reporter: | akr <akr> |
| Component: | ia64 | Assignee: | freebsd-ia64 (Nobody) <ia64> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 6.0-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
State Changed From-To: open->patched Fix committed to -CURRENT and will be merged onto the 6.x branch in a week. Thanks! State Changed From-To: patched->closed Fixed as of version 6.1. |
On IA64 (and other LP64 environments), (int)FD_ISSET(32, &fds) is evaluated to 0, even if 32 is set in fds. Since SUSv3 defines FD_ISSET defines as follows, cast to int should be safe. int FD_ISSET(int fd, fd_set *fdset); This problem is caused because FD_ISSET() returns single unsigned long bitmap. (__fds_bits is an array of unsigned long) td150.testdrive.hp.com> grep FD_ISSET /usr/include/sys/select.h #define FD_ISSET(n, p) ((p)->__fds_bits[(n)/_NFDBITS] & __fdset_mask(n)) Since unsigned long is longer than int on LP64, (int)FD_ISSET() discards upper 32bits. Fix: add "!= 0". #define FD_ISSET(n, p) (((p)->__fds_bits[(n)/_NFDBITS] & __fdset_mask(n)) != 0) How-To-Repeat: td150.testdrive.hp.com> cat tst.c #include <stdio.h> #include <sys/select.h> int main() { fd_set fds; FD_ZERO(&fds); FD_SET(32, &fds); printf("%d\n", (int)FD_ISSET(32, &fds)); printf("%lx\n", (long)FD_ISSET(32, &fds)); return 0; } td150.testdrive.hp.com> gcc tst.c td150.testdrive.hp.com> ./a.out 0 100000000