1 /* poll.cc. Implements poll(2) via usage of select(2) call.
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9 #define FD_SETSIZE 16384 // lots of fds
12 #include <sys/param.h>
14 #define USE_SYS_TYPES_FD_SET
25 poll (struct pollfd
*fds
, nfds_t nfds
, int timeout
)
29 fd_set
*read_fds
, *write_fds
, *except_fds
;
30 struct timeval tv
= { timeout
/ 1000, (timeout
% 1000) * 1000 };
32 for (unsigned int i
= 0; i
< nfds
; ++i
)
33 if (fds
[i
].fd
> max_fd
)
36 size_t fds_size
= howmany (max_fd
+ 1, NFDBITS
) * sizeof (fd_mask
);
38 read_fds
= (fd_set
*) alloca (fds_size
);
39 write_fds
= (fd_set
*) alloca (fds_size
);
40 except_fds
= (fd_set
*) alloca (fds_size
);
42 if (!read_fds
|| !write_fds
|| !except_fds
)
44 set_errno (EINVAL
); /* According to SUSv3. */
48 memset (read_fds
, 0, fds_size
);
49 memset (write_fds
, 0, fds_size
);
50 memset (except_fds
, 0, fds_size
);
52 for (unsigned int i
= 0; i
< nfds
; ++i
)
55 if (!cygheap
->fdtab
.not_open (fds
[i
].fd
))
57 if (fds
[i
].events
& POLLIN
)
58 FD_SET(fds
[i
].fd
, read_fds
);
59 if (fds
[i
].events
& POLLOUT
)
60 FD_SET(fds
[i
].fd
, write_fds
);
61 if (fds
[i
].events
& POLLPRI
)
62 FD_SET(fds
[i
].fd
, except_fds
);
64 else if (fds
[i
].fd
>= 0)
67 fds
[i
].revents
= POLLNVAL
;
74 /* Only invalid fds? Return. */
75 if ((nfds_t
) invalid_fds
== nfds
)
77 /* POSIX doesn't explicitely define this behaviour, but on Linux,
78 the timeout is set to 0 if an error occurs, and POLLNVAL is one
79 of these errors. So, for Linux-compatibility's sake... */
80 tv
.tv_sec
= tv
.tv_usec
= 0;
83 int ret
= cygwin_select (max_fd
+ 1, read_fds
, write_fds
, except_fds
,
84 timeout
< 0 ? NULL
: &tv
);
85 /* timeout, signal, whatever? Return. If invalid fds exist, return with
88 return invalid_fds
?: ret
;
90 /* Set revents fields and count fds with non-zero revents fields for
93 for (unsigned int i
= 0; i
< nfds
; ++i
)
95 if (fds
[i
].fd
>= 0 && fds
[i
].revents
!= POLLNVAL
)
97 fhandler_socket_wsock
*sock
;
99 /* Check if the descriptor has been closed, or if shutdown for the
100 read side has been called on a socket. */
101 if (cygheap
->fdtab
.not_open (fds
[i
].fd
)
102 || ((sock
= cygheap
->fdtab
[fds
[i
].fd
]->is_wsock_socket ())
103 && sock
->saw_shutdown_read ()))
104 fds
[i
].revents
= POLLHUP
;
107 if ((fds
[i
].events
& POLLIN
) && FD_ISSET(fds
[i
].fd
, read_fds
))
108 /* This should be sufficient for sockets, too. Using
109 MSG_PEEK, as before, can be considered dangerous at
110 best. Quote from W. Richard Stevens: "The presence
111 of an error can be considered either normal data or
112 an error (POLLERR). In either case, a subsequent read
113 will return -1 with errno set to the appropriate value."
114 So it looks like there's actually no good reason to
116 fds
[i
].revents
|= POLLIN
;
117 /* Handle failed connect. A failed connect implicitly sets
118 POLLOUT, if requested, but it doesn't set POLLIN. */
119 if ((fds
[i
].events
& POLLIN
)
120 && (sock
= cygheap
->fdtab
[fds
[i
].fd
]->is_wsock_socket ())
121 && sock
->connect_state () == connect_failed
)
122 fds
[i
].revents
|= (POLLIN
| POLLERR
);
125 if ((fds
[i
].events
& POLLOUT
)
126 && FD_ISSET(fds
[i
].fd
, write_fds
))
127 fds
[i
].revents
|= POLLOUT
;
128 if ((fds
[i
].events
& POLLPRI
)
129 && FD_ISSET(fds
[i
].fd
, except_fds
))
130 fds
[i
].revents
|= POLLPRI
;
137 /* Number of fds with event includes the invalid fds. */
138 return ret
+ invalid_fds
;
142 ppoll (struct pollfd
*fds
, nfds_t nfds
, const struct timespec
*timeout_ts
,
143 const sigset_t
*sigmask
)
146 sigset_t oldset
= _my_tls
.sigmask
;
150 timeout
= (timeout_ts
== NULL
)
152 : (timeout_ts
->tv_sec
* 1000 + timeout_ts
->tv_nsec
/ 1000000);
154 set_signal_mask (_my_tls
.sigmask
, *sigmask
);
155 int ret
= poll (fds
, nfds
, timeout
);
157 set_signal_mask (_my_tls
.sigmask
, oldset
);