Daemon News Ezine BSD News BSD Mall BSD Support Forum BSD Advocacy BSD Updates

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ia64/91421: FD_ISSET returns long, not int.

>Number:         91421
>Category:       ia64
>Synopsis:       FD_ISSET returns long, not int.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ia64
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jan 06 21:10:02 GMT 2006
>Originator:     Tanaka Akira
>Release:        6.0-RELEASE
FreeBSD td150.testdrive.hp.com 6.0-RELEASE FreeBSD 6.0-RELEASE #0: Wed Nov  2 10:01:27 UTC 2005     root@xxxxxxxxxxxxxxxxxx:/usr/obj/usr/src/sys/GENERIC  ia64

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.

td150.testdrive.hp.com> cat tst.c
#include <stdio.h>
#include <sys/select.h>

int main()
  fd_set 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

add "!= 0".

#define FD_ISSET(n, p)  (((p)->__fds_bits[(n)/_NFDBITS] & __fdset_mask(n)) != 0)