1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
18
/* POSIX defines 1024 for the FD_SETSIZE */
19
#define FD_SETSIZE 1024
25
#include "apr_portable.h"
26
#include "apr_arch_networkio.h"
27
#include "apr_arch_file_io.h"
28
#include "apr_arch_poll_private.h"
30
#ifdef POLL_USES_SELECT
32
APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, int num,
34
apr_interval_time_t timeout)
36
fd_set readset, writeset, exceptset;
39
struct timeval tv, *tvptr;
41
apr_datatype_e set_type = APR_NO_DESC;
48
tv.tv_sec = (long) apr_time_sec(timeout);
49
tv.tv_usec = (long) apr_time_usec(timeout);
57
for (i = 0; i < num; i++) {
60
aprset[i].rtnevents = 0;
62
if (aprset[i].desc_type == APR_POLL_SOCKET) {
64
if (HAS_PIPES(set_type)) {
68
set_type = APR_POLL_SOCKET;
71
fd = aprset[i].desc.s->socketdes;
73
else if (aprset[i].desc_type == APR_POLL_FILE) {
74
#if !APR_FILES_AS_SOCKETS
78
if (aprset[i].desc.f->is_pipe && !HAS_SOCKETS(set_type)) {
79
set_type = APR_POLL_FILE;
85
fd = aprset[i].desc.f->filedes;
87
#endif /* APR_FILES_AS_SOCKETS */
92
#if !defined(WIN32) && !defined(NETWARE) /* socket sets handled with array of handles */
93
if (fd >= FD_SETSIZE) {
94
/* XXX invent new error code so application has a clue */
98
if (aprset[i].reqevents & APR_POLLIN) {
101
if (aprset[i].reqevents & APR_POLLOUT) {
102
FD_SET(fd, &writeset);
104
if (aprset[i].reqevents &
105
(APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) {
106
FD_SET(fd, &exceptset);
108
if ((int) fd > maxfd) {
114
if (HAS_PIPES(set_type)) {
115
rv = pipe_select(maxfd + 1, &readset, &writeset, &exceptset, tvptr);
120
rv = select(maxfd + 1, &readset, &writeset, &exceptset, tvptr);
131
return apr_get_netos_error();
135
for (i = 0; i < num; i++) {
138
if (aprset[i].desc_type == APR_POLL_SOCKET) {
139
fd = aprset[i].desc.s->socketdes;
141
else if (aprset[i].desc_type == APR_POLL_FILE) {
142
#if !APR_FILES_AS_SOCKETS
145
fd = aprset[i].desc.f->filedes;
151
if (FD_ISSET(fd, &readset)) {
152
aprset[i].rtnevents |= APR_POLLIN;
154
if (FD_ISSET(fd, &writeset)) {
155
aprset[i].rtnevents |= APR_POLLOUT;
157
if (FD_ISSET(fd, &exceptset)) {
158
aprset[i].rtnevents |= APR_POLLERR;
160
if (aprset[i].rtnevents) {
168
#endif /* POLL_USES_SELECT */
170
#ifdef POLLSET_USES_SELECT
178
fd_set readset, writeset, exceptset;
180
apr_pollfd_t *query_set;
181
apr_pollfd_t *result_set;
187
APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
192
if (flags & APR_POLLSET_THREADSAFE) {
197
if (size > FD_SETSIZE) {
202
*pollset = apr_palloc(p, sizeof(**pollset));
203
(*pollset)->nelts = 0;
204
(*pollset)->nalloc = size;
205
(*pollset)->pool = p;
206
FD_ZERO(&((*pollset)->readset));
207
FD_ZERO(&((*pollset)->writeset));
208
FD_ZERO(&((*pollset)->exceptset));
209
(*pollset)->maxfd = 0;
211
(*pollset)->set_type = APR_NO_DESC;
213
(*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
214
(*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
219
APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset)
224
APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
225
const apr_pollfd_t *descriptor)
229
if (pollset->nelts == pollset->nalloc) {
233
pollset->query_set[pollset->nelts] = *descriptor;
235
if (descriptor->desc_type == APR_POLL_SOCKET) {
237
/* NetWare can't handle mixed descriptor types in select() */
238
if (HAS_PIPES(pollset->set_type)) {
242
pollset->set_type = APR_POLL_SOCKET;
245
fd = descriptor->desc.s->socketdes;
248
#if !APR_FILES_AS_SOCKETS
252
/* NetWare can't handle mixed descriptor types in select() */
253
if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->set_type)) {
254
pollset->set_type = APR_POLL_FILE;
255
fd = descriptor->desc.f->filedes;
261
fd = descriptor->desc.f->filedes;
265
#if !defined(WIN32) && !defined(NETWARE) /* socket sets handled with array of handles */
266
if (fd >= FD_SETSIZE) {
267
/* XXX invent new error code so application has a clue */
271
if (descriptor->reqevents & APR_POLLIN) {
272
FD_SET(fd, &(pollset->readset));
274
if (descriptor->reqevents & APR_POLLOUT) {
275
FD_SET(fd, &(pollset->writeset));
277
if (descriptor->reqevents &
278
(APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) {
279
FD_SET(fd, &(pollset->exceptset));
281
if ((int) fd > pollset->maxfd) {
282
pollset->maxfd = (int) fd;
288
APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t * pollset,
289
const apr_pollfd_t * descriptor)
294
if (descriptor->desc_type == APR_POLL_SOCKET) {
295
fd = descriptor->desc.s->socketdes;
298
#if !APR_FILES_AS_SOCKETS
301
fd = descriptor->desc.f->filedes;
305
for (i = 0; i < pollset->nelts; i++) {
306
if (descriptor->desc.s == pollset->query_set[i].desc.s) {
307
/* Found an instance of the fd: remove this and any other copies */
308
apr_uint32_t dst = i;
309
apr_uint32_t old_nelts = pollset->nelts;
311
for (i++; i < old_nelts; i++) {
312
if (descriptor->desc.s == pollset->query_set[i].desc.s) {
316
pollset->query_set[dst] = pollset->query_set[i];
320
FD_CLR(fd, &(pollset->readset));
321
FD_CLR(fd, &(pollset->writeset));
322
FD_CLR(fd, &(pollset->exceptset));
323
if (((int) fd == pollset->maxfd) && (pollset->maxfd > 0)) {
333
APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
334
apr_interval_time_t timeout,
336
const apr_pollfd_t **descriptors)
340
struct timeval tv, *tvptr;
341
fd_set readset, writeset, exceptset;
347
tv.tv_sec = (long) apr_time_sec(timeout);
348
tv.tv_usec = (long) apr_time_usec(timeout);
352
memcpy(&readset, &(pollset->readset), sizeof(fd_set));
353
memcpy(&writeset, &(pollset->writeset), sizeof(fd_set));
354
memcpy(&exceptset, &(pollset->exceptset), sizeof(fd_set));
357
if (HAS_PIPES(pollset->set_type)) {
358
rv = pipe_select(pollset->maxfd + 1, &readset, &writeset, &exceptset,
363
rv = select(pollset->maxfd + 1, &readset, &writeset, &exceptset,
368
return apr_get_netos_error();
374
for (i = 0; i < pollset->nelts; i++) {
376
if (pollset->query_set[i].desc_type == APR_POLL_SOCKET) {
377
fd = pollset->query_set[i].desc.s->socketdes;
380
#if !APR_FILES_AS_SOCKETS
383
fd = pollset->query_set[i].desc.f->filedes;
386
if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) ||
387
FD_ISSET(fd, &exceptset)) {
388
pollset->result_set[j] = pollset->query_set[i];
389
pollset->result_set[j].rtnevents = 0;
390
if (FD_ISSET(fd, &readset)) {
391
pollset->result_set[j].rtnevents |= APR_POLLIN;
393
if (FD_ISSET(fd, &writeset)) {
394
pollset->result_set[j].rtnevents |= APR_POLLOUT;
396
if (FD_ISSET(fd, &exceptset)) {
397
pollset->result_set[j].rtnevents |= APR_POLLERR;
405
*descriptors = pollset->result_set;
409
#endif /* POLLSET_USES_SELECT */