📄 poll.c
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include "apr.h"#include "apr_poll.h"#include "apr_time.h"#include "apr_portable.h"#include "apr_arch_networkio.h"#include "apr_arch_file_io.h"#if HAVE_POLL_H#include <poll.h>#endif#if HAVE_SYS_POLL_H#include <sys/poll.h>#endif#if HAVE_ALLOCA_H#include <alloca.h>#endif#ifdef NETWARE#define HAS_SOCKETS(dt) (dt == APR_POLL_SOCKET) ? 1 : 0#define HAS_PIPES(dt) (dt == APR_POLL_FILE) ? 1 : 0#endif#ifdef HAVE_POLL /* We can just use poll to do our socket polling. */static apr_int16_t get_event(apr_int16_t event){ apr_int16_t rv = 0; if (event & APR_POLLIN) rv |= POLLIN; if (event & APR_POLLPRI) rv |= POLLPRI; if (event & APR_POLLOUT) rv |= POLLOUT; if (event & APR_POLLERR) rv |= POLLERR; if (event & APR_POLLHUP) rv |= POLLHUP; if (event & APR_POLLNVAL) rv |= POLLNVAL; return rv;}static apr_int16_t get_revent(apr_int16_t event){ apr_int16_t rv = 0; if (event & POLLIN) rv |= APR_POLLIN; if (event & POLLPRI) rv |= APR_POLLPRI; if (event & POLLOUT) rv |= APR_POLLOUT; if (event & POLLERR) rv |= APR_POLLERR; if (event & POLLHUP) rv |= APR_POLLHUP; if (event & POLLNVAL) rv |= APR_POLLNVAL; return rv;} #define SMALL_POLLSET_LIMIT 8APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t num, apr_int32_t *nsds, apr_interval_time_t timeout){ int i, num_to_poll;#ifdef HAVE_VLA /* XXX: I trust that this is a segv when insufficient stack exists? */ struct pollfd pollset[num];#elif defined(HAVE_ALLOCA) struct pollfd *pollset = alloca(sizeof(struct pollfd) * num); if (!pollset) return APR_ENOMEM;#else struct pollfd tmp_pollset[SMALL_POLLSET_LIMIT]; struct pollfd *pollset; if (num <= SMALL_POLLSET_LIMIT) { pollset = tmp_pollset; } else { /* This does require O(n) to copy the descriptors to the internal * mapping. */ pollset = malloc(sizeof(struct pollfd) * num); /* The other option is adding an apr_pool_abort() fn to invoke * the pool's out of memory handler */ if (!pollset) return APR_ENOMEM; }#endif for (i = 0; i < num; i++) { if (aprset[i].desc_type == APR_POLL_SOCKET) { pollset[i].fd = aprset[i].desc.s->socketdes; } else if (aprset[i].desc_type == APR_POLL_FILE) { pollset[i].fd = aprset[i].desc.f->filedes; } else { break; } pollset[i].events = get_event(aprset[i].reqevents); } num_to_poll = i; if (timeout > 0) { timeout /= 1000; /* convert microseconds to milliseconds */ } i = poll(pollset, num_to_poll, timeout); (*nsds) = i; for (i = 0; i < num; i++) { aprset[i].rtnevents = get_revent(pollset[i].revents); } #if !defined(HAVE_VLA) && !defined(HAVE_ALLOCA) if (num > SMALL_POLLSET_LIMIT) { free(pollset); }#endif if ((*nsds) < 0) { return apr_get_netos_error(); } if ((*nsds) == 0) { return APR_TIMEUP; } return APR_SUCCESS;}#else /* Use select to mimic poll */APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, int num, apr_int32_t *nsds, apr_interval_time_t timeout){ fd_set readset, writeset, exceptset; int rv, i; int maxfd = -1; struct timeval tv, *tvptr;#ifdef NETWARE apr_datatype_e set_type = APR_NO_DESC;#endif if (timeout < 0) { tvptr = NULL; } else { tv.tv_sec = (long)apr_time_sec(timeout); tv.tv_usec = (long)apr_time_usec(timeout); tvptr = &tv; } FD_ZERO(&readset); FD_ZERO(&writeset); FD_ZERO(&exceptset); for (i = 0; i < num; i++) { apr_os_sock_t fd; aprset[i].rtnevents = 0; if (aprset[i].desc_type == APR_POLL_SOCKET) {#ifdef NETWARE if (HAS_PIPES(set_type)) { return APR_EBADF; } else { set_type = APR_POLL_SOCKET; }#endif fd = aprset[i].desc.s->socketdes; } else if (aprset[i].desc_type == APR_POLL_FILE) {#if !APR_FILES_AS_SOCKETS return APR_EBADF;#else#ifdef NETWARE if (aprset[i].desc.f->is_pipe && !HAS_SOCKETS(set_type)) { set_type = APR_POLL_FILE; } else return APR_EBADF;#endif /* NETWARE */ fd = aprset[i].desc.f->filedes;#endif /* APR_FILES_AS_SOCKETS */ } else { break; }#if !defined(WIN32) && !defined(NETWARE) /* socket sets handled with array of handles */ if (fd >= FD_SETSIZE) { /* XXX invent new error code so application has a clue */ return APR_EBADF; }#endif if (aprset[i].reqevents & APR_POLLIN) { FD_SET(fd, &readset); } if (aprset[i].reqevents & APR_POLLOUT) { FD_SET(fd, &writeset); } if (aprset[i].reqevents & (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) { FD_SET(fd, &exceptset); } if ((int)fd > maxfd) { maxfd = (int)fd; } }#ifdef NETWARE if (HAS_PIPES(set_type)) { rv = pipe_select(maxfd + 1, &readset, &writeset, &exceptset, tvptr); } else {#endif rv = select(maxfd + 1, &readset, &writeset, &exceptset, tvptr);#ifdef NETWARE }#endif (*nsds) = rv; if ((*nsds) == 0) { return APR_TIMEUP; } if ((*nsds) < 0) { return apr_get_netos_error(); } for (i = 0; i < num; i++) { apr_os_sock_t fd; if (aprset[i].desc_type == APR_POLL_SOCKET) { fd = aprset[i].desc.s->socketdes; } else if (aprset[i].desc_type == APR_POLL_FILE) {#if !APR_FILES_AS_SOCKETS return APR_EBADF;#else fd = aprset[i].desc.f->filedes;#endif } else { break; } if (FD_ISSET(fd, &readset)) { aprset[i].rtnevents |= APR_POLLIN; } if (FD_ISSET(fd, &writeset)) { aprset[i].rtnevents |= APR_POLLOUT; } if (FD_ISSET(fd, &exceptset)) { aprset[i].rtnevents |= APR_POLLERR; } } return APR_SUCCESS;}#endif struct apr_pollset_t { apr_uint32_t nelts; apr_uint32_t nalloc;#ifdef HAVE_POLL struct pollfd *pollset;#else fd_set readset, writeset, exceptset; int maxfd;#endif apr_pollfd_t *query_set; apr_pollfd_t *result_set; apr_pool_t *pool;#ifdef NETWARE int set_type;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -