diff options
Diffstat (limited to 'poll')
-rw-r--r-- | poll/unix/epoll.c | 43 | ||||
-rw-r--r-- | poll/unix/kqueue.c | 44 | ||||
-rw-r--r-- | poll/unix/poll.c | 28 | ||||
-rw-r--r-- | poll/unix/pollcb.c | 63 | ||||
-rw-r--r-- | poll/unix/pollset.c | 141 | ||||
-rw-r--r-- | poll/unix/port.c | 105 | ||||
-rw-r--r-- | poll/unix/select.c | 10 | ||||
-rw-r--r-- | poll/unix/wakeup.c | 151 | ||||
-rw-r--r-- | poll/unix/z_asio.c | 19 |
9 files changed, 365 insertions, 239 deletions
diff --git a/poll/unix/epoll.c b/poll/unix/epoll.c index fe006db013c0..4ab03f67ccc1 100644 --- a/poll/unix/epoll.c +++ b/poll/unix/epoll.c @@ -157,7 +157,7 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { struct epoll_event ev = {0}; - int ret = -1; + int ret; pfd_elem_t *elem = NULL; apr_status_t rv = APR_SUCCESS; @@ -214,7 +214,7 @@ static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, struct epoll_event ev = {0}; /* ignored, but must be passed with * kernel < 2.6.9 */ - int ret = -1; + int ret; if (descriptor->desc_type == APR_POLL_SOCKET) { ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_DEL, @@ -255,9 +255,10 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, apr_int32_t *num, const apr_pollfd_t **descriptors) { - int ret, i, j; + int ret; apr_status_t rv = APR_SUCCESS; - apr_pollfd_t *fdptr; + + *num = 0; if (timeout > 0) { timeout /= 1000; @@ -265,8 +266,6 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, ret = epoll_wait(pollset->p->epoll_fd, pollset->p->pollset, pollset->nalloc, timeout); - (*num) = ret; - if (ret < 0) { rv = apr_get_netos_error(); } @@ -274,6 +273,9 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, rv = APR_TIMEUP; } else { + int i, j; + const apr_pollfd_t *fdptr; + for (i = 0, j = 0; i < ret; i++) { if (pollset->flags & APR_POLLSET_NOCOPY) { fdptr = (apr_pollfd_t *)(pollset->p->pollset[i].data.ptr); @@ -287,7 +289,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, if ((pollset->flags & APR_POLLSET_WAKEABLE) && fdptr->desc_type == APR_POLL_FILE && fdptr->desc.f == pollset->wakeup_pipe[0]) { - apr_pollset_drain_wakeup_pipe(pollset); + apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe); rv = APR_EINTR; } else { @@ -318,7 +320,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, return rv; } -static apr_pollset_provider_t impl = { +static const apr_pollset_provider_t impl = { impl_pollset_create, impl_pollset_add, impl_pollset_remove, @@ -327,11 +329,10 @@ static apr_pollset_provider_t impl = { "epoll" }; -apr_pollset_provider_t *apr_pollset_provider_epoll = &impl; +const apr_pollset_provider_t *const apr_pollset_provider_epoll = &impl; -static apr_status_t cb_cleanup(void *p_) +static apr_status_t impl_pollcb_cleanup(apr_pollcb_t *pollcb) { - apr_pollcb_t *pollcb = (apr_pollcb_t *) p_; close(pollcb->fd); return APR_SUCCESS; } @@ -377,7 +378,6 @@ static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb, pollcb->fd = fd; pollcb->pollset.epoll = apr_palloc(p, size * sizeof(struct epoll_event)); - apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null); return APR_SUCCESS; } @@ -385,11 +385,11 @@ static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb, static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb, apr_pollfd_t *descriptor) { - struct epoll_event ev; + struct epoll_event ev = { 0 }; int ret; ev.events = get_epoll_event(descriptor->reqevents); - ev.data.ptr = (void *)descriptor; + ev.data.ptr = (void *) descriptor; if (descriptor->desc_type == APR_POLL_SOCKET) { ret = epoll_ctl(pollcb->fd, EPOLL_CTL_ADD, @@ -414,7 +414,7 @@ static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb, struct epoll_event ev = {0}; /* ignored, but must be passed with * kernel < 2.6.9 */ - int ret = -1; + int ret; if (descriptor->desc_type == APR_POLL_SOCKET) { ret = epoll_ctl(pollcb->fd, EPOLL_CTL_DEL, @@ -456,6 +456,14 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, else { for (i = 0; i < ret; i++) { apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.epoll[i].data.ptr); + + if ((pollcb->flags & APR_POLLSET_WAKEABLE) && + pollfd->desc_type == APR_POLL_FILE && + pollfd->desc.f == pollcb->wakeup_pipe[0]) { + apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe); + return APR_EINTR; + } + pollfd->rtnevents = get_epoll_revent(pollcb->pollset.epoll[i].events); rv = func(baton, pollfd); @@ -468,14 +476,15 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, return rv; } -static apr_pollcb_provider_t impl_cb = { +static const apr_pollcb_provider_t impl_cb = { impl_pollcb_create, impl_pollcb_add, impl_pollcb_remove, impl_pollcb_poll, + impl_pollcb_cleanup, "epoll" }; -apr_pollcb_provider_t *apr_pollcb_provider_epoll = &impl_cb; +const apr_pollcb_provider_t *const apr_pollcb_provider_epoll = &impl_cb; #endif /* HAVE_EPOLL */ diff --git a/poll/unix/kqueue.c b/poll/unix/kqueue.c index efc589869a69..548464db148a 100644 --- a/poll/unix/kqueue.c +++ b/poll/unix/kqueue.c @@ -254,10 +254,11 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, apr_int32_t *num, const apr_pollfd_t **descriptors) { - int ret, i, j; + int ret; struct timespec tv, *tvptr; apr_status_t rv = APR_SUCCESS; - apr_pollfd_t fd; + + *num = 0; if (timeout < 0) { tvptr = NULL; @@ -270,7 +271,6 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, ret = kevent(pollset->p->kqueue_fd, NULL, 0, pollset->p->ke_set, pollset->p->setsize, tvptr); - (*num) = ret; if (ret < 0) { rv = apr_get_netos_error(); } @@ -278,16 +278,19 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, rv = APR_TIMEUP; } else { + int i, j; + const apr_pollfd_t *fd; + for (i = 0, j = 0; i < ret; i++) { - fd = (((pfd_elem_t*)(pollset->p->ke_set[i].udata))->pfd); + fd = &((pfd_elem_t *)pollset->p->ke_set[i].udata)->pfd; if ((pollset->flags & APR_POLLSET_WAKEABLE) && - fd.desc_type == APR_POLL_FILE && - fd.desc.f == pollset->wakeup_pipe[0]) { - apr_pollset_drain_wakeup_pipe(pollset); + fd->desc_type == APR_POLL_FILE && + fd->desc.f == pollset->wakeup_pipe[0]) { + apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe); rv = APR_EINTR; } else { - pollset->p->result_set[j] = fd; + pollset->p->result_set[j] = *fd; pollset->p->result_set[j].rtnevents = get_kqueue_revent(pollset->p->ke_set[i].filter, pollset->p->ke_set[i].flags); @@ -302,7 +305,6 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, } } - pollset_lock_rings(); /* Shift all PFDs in the Dead Ring to the Free Ring */ @@ -314,7 +316,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, return rv; } -static apr_pollset_provider_t impl = { +static const apr_pollset_provider_t impl = { impl_pollset_create, impl_pollset_add, impl_pollset_remove, @@ -323,11 +325,10 @@ static apr_pollset_provider_t impl = { "kqueue" }; -apr_pollset_provider_t *apr_pollset_provider_kqueue = &impl; +const apr_pollset_provider_t *apr_pollset_provider_kqueue = &impl; -static apr_status_t cb_cleanup(void *b_) +static apr_status_t impl_pollcb_cleanup(apr_pollcb_t *pollcb) { - apr_pollcb_t *pollcb = (apr_pollcb_t *) b_; close(pollcb->fd); return APR_SUCCESS; } @@ -365,8 +366,7 @@ static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb, } pollcb->fd = fd; - pollcb->pollset.ke = (struct kevent *)apr_pcalloc(p, 2 * size * sizeof(struct kevent)); - apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null); + pollcb->pollset.ke = (struct kevent *) apr_pcalloc(p, 2 * size * sizeof(struct kevent)); return APR_SUCCESS; } @@ -469,7 +469,14 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, else { for (i = 0; i < ret; i++) { apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.ke[i].udata); - + + if ((pollcb->flags & APR_POLLSET_WAKEABLE) && + pollfd->desc_type == APR_POLL_FILE && + pollfd->desc.f == pollcb->wakeup_pipe[0]) { + apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe); + return APR_EINTR; + } + pollfd->rtnevents = get_kqueue_revent(pollcb->pollset.ke[i].filter, pollcb->pollset.ke[i].flags); @@ -484,14 +491,15 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, return rv; } -static apr_pollcb_provider_t impl_cb = { +static const apr_pollcb_provider_t impl_cb = { impl_pollcb_create, impl_pollcb_add, impl_pollcb_remove, impl_pollcb_poll, + impl_pollcb_cleanup, "kqueue" }; -apr_pollcb_provider_t *apr_pollcb_provider_kqueue = &impl_cb; +const apr_pollcb_provider_t *apr_pollcb_provider_kqueue = &impl_cb; #endif /* HAVE_KQUEUE */ diff --git a/poll/unix/poll.c b/poll/unix/poll.c index d7a436fd9a14..f148f5e50d3d 100644 --- a/poll/unix/poll.c +++ b/poll/unix/poll.c @@ -241,10 +241,11 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, int ret; apr_status_t rv = APR_SUCCESS; + *num = 0; + #ifdef WIN32 /* WSAPoll() requires at least one socket. */ if (pollset->nelts == 0) { - *num = 0; if (timeout > 0) { apr_sleep(timeout); return APR_TIMEUP; @@ -261,7 +262,6 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, } ret = poll(pollset->p->pollset, pollset->nelts, timeout); #endif - (*num) = ret; if (ret < 0) { return apr_get_netos_error(); } @@ -279,8 +279,8 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, if ((pollset->flags & APR_POLLSET_WAKEABLE) && pollset->p->query_set[i].desc_type == APR_POLL_FILE && pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) { - apr_pollset_drain_wakeup_pipe(pollset); - rv = APR_EINTR; + apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe); + rv = APR_EINTR; } else { pollset->p->result_set[j] = pollset->p->query_set[i]; @@ -290,15 +290,16 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, } } } - if (((*num) = j) > 0) + if ((*num = j)) { /* any event besides wakeup pipe? */ rv = APR_SUCCESS; + } } if (descriptors && (*num)) *descriptors = pollset->p->result_set; return rv; } -static apr_pollset_provider_t impl = { +static const apr_pollset_provider_t impl = { impl_pollset_create, impl_pollset_add, impl_pollset_remove, @@ -307,7 +308,7 @@ static apr_pollset_provider_t impl = { "poll" }; -apr_pollset_provider_t *apr_pollset_provider_poll = &impl; +const apr_pollset_provider_t *apr_pollset_provider_poll = &impl; /* Poll method pollcb. * This is probably usable only for WIN32 having WSAPoll @@ -426,6 +427,14 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, for (i = 0; i < pollcb->nelts; i++) { if (pollcb->pollset.ps[i].revents != 0) { apr_pollfd_t *pollfd = pollcb->copyset[i]; + + if ((pollcb->flags & APR_POLLSET_WAKEABLE) && + pollfd->desc_type == APR_POLL_FILE && + pollfd->desc.f == pollcb->wakeup_pipe[0]) { + apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe); + return APR_EINTR; + } + pollfd->rtnevents = get_revent(pollcb->pollset.ps[i].revents); rv = func(baton, pollfd); if (rv) { @@ -437,14 +446,15 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, return rv; } -static apr_pollcb_provider_t impl_cb = { +static const apr_pollcb_provider_t impl_cb = { impl_pollcb_create, impl_pollcb_add, impl_pollcb_remove, impl_pollcb_poll, + NULL, "poll" }; -apr_pollcb_provider_t *apr_pollcb_provider_poll = &impl_cb; +const apr_pollcb_provider_t *apr_pollcb_provider_poll = &impl_cb; #endif /* HAVE_POLL */ diff --git a/poll/unix/pollcb.c b/poll/unix/pollcb.c index da12f015a74f..a63ad5c9cad2 100644 --- a/poll/unix/pollcb.c +++ b/poll/unix/pollcb.c @@ -29,21 +29,21 @@ static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD; #if defined(HAVE_KQUEUE) -extern apr_pollcb_provider_t *apr_pollcb_provider_kqueue; +extern const apr_pollcb_provider_t *apr_pollcb_provider_kqueue; #endif #if defined(HAVE_PORT_CREATE) -extern apr_pollcb_provider_t *apr_pollcb_provider_port; +extern const apr_pollcb_provider_t *apr_pollcb_provider_port; #endif #if defined(HAVE_EPOLL) -extern apr_pollcb_provider_t *apr_pollcb_provider_epoll; +extern const apr_pollcb_provider_t *apr_pollcb_provider_epoll; #endif #if defined(HAVE_POLL) -extern apr_pollcb_provider_t *apr_pollcb_provider_poll; +extern const apr_pollcb_provider_t *apr_pollcb_provider_poll; #endif -static apr_pollcb_provider_t *pollcb_provider(apr_pollset_method_e method) +static const apr_pollcb_provider_t *pollcb_provider(apr_pollset_method_e method) { - apr_pollcb_provider_t *provider = NULL; + const apr_pollcb_provider_t *provider = NULL; switch (method) { case APR_POLLSET_KQUEUE: #if defined(HAVE_KQUEUE) @@ -73,6 +73,20 @@ static apr_pollcb_provider_t *pollcb_provider(apr_pollset_method_e method) return provider; } +static apr_status_t pollcb_cleanup(void *p) +{ + apr_pollcb_t *pollcb = (apr_pollcb_t *) p; + + if (pollcb->provider->cleanup) { + (*pollcb->provider->cleanup)(pollcb); + } + if (pollcb->flags & APR_POLLSET_WAKEABLE) { + apr_poll_close_wakeup_pipe(pollcb->wakeup_pipe); + } + + return APR_SUCCESS; +} + APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb, apr_uint32_t size, apr_pool_t *p, @@ -81,7 +95,7 @@ APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb, { apr_status_t rv; apr_pollcb_t *pollcb; - apr_pollcb_provider_t *provider = NULL; + const apr_pollcb_provider_t *provider = NULL; *ret_pollcb = NULL; @@ -109,9 +123,15 @@ APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb, } } + if (flags & APR_POLLSET_WAKEABLE) { + /* Add room for wakeup descriptor */ + size++; + } + pollcb = apr_palloc(p, sizeof(*pollcb)); pollcb->nelts = 0; pollcb->nalloc = size; + pollcb->flags = flags; pollcb->pool = p; pollcb->provider = provider; @@ -140,6 +160,22 @@ APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb, return rv; } + if (flags & APR_POLLSET_WAKEABLE) { + /* Create wakeup pipe */ + if ((rv = apr_poll_create_wakeup_pipe(pollcb->pool, &pollcb->wakeup_pfd, + pollcb->wakeup_pipe)) + != APR_SUCCESS) { + return rv; + } + + if ((rv = apr_pollcb_add(pollcb, &pollcb->wakeup_pfd)) != APR_SUCCESS) { + return rv; + } + } + if ((flags & APR_POLLSET_WAKEABLE) || provider->cleanup) + apr_pool_cleanup_register(p, pollcb, pollcb_cleanup, + apr_pool_cleanup_null); + *ret_pollcb = pollcb; return APR_SUCCESS; } @@ -173,3 +209,16 @@ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, { return (*pollcb->provider->poll)(pollcb, timeout, func, baton); } + +APR_DECLARE(apr_status_t) apr_pollcb_wakeup(apr_pollcb_t *pollcb) +{ + if (pollcb->flags & APR_POLLSET_WAKEABLE) + return apr_file_putc(1, pollcb->wakeup_pipe[1]); + else + return APR_EINIT; +} + +APR_DECLARE(const char *) apr_pollcb_method_name(apr_pollcb_t *pollcb) +{ + return pollcb->provider->name; +} diff --git a/poll/unix/pollset.c b/poll/unix/pollset.c index 852d74597fcc..8fa817330f65 100644 --- a/poll/unix/pollset.c +++ b/poll/unix/pollset.c @@ -30,101 +30,6 @@ static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD; -#if !APR_FILES_AS_SOCKETS -#if defined (WIN32) - -/* Create a dummy wakeup socket pipe for interrupting the poller - */ -static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset) -{ - apr_status_t rv; - - if ((rv = apr_file_socket_pipe_create(&pollset->wakeup_pipe[0], - &pollset->wakeup_pipe[1], - pollset->pool)) != APR_SUCCESS) - return rv; - - pollset->wakeup_pfd.p = pollset->pool; - pollset->wakeup_pfd.reqevents = APR_POLLIN; - pollset->wakeup_pfd.desc_type = APR_POLL_FILE; - pollset->wakeup_pfd.desc.f = pollset->wakeup_pipe[0]; - - return apr_pollset_add(pollset, &pollset->wakeup_pfd); -} - -#else /* !WIN32 */ -static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset) -{ - return APR_ENOTIMPL; -} - -static apr_status_t apr_file_socket_pipe_close(apr_file_t *file) -{ - return APR_ENOTIMPL; -} - -#endif /* WIN32 */ -#else /* APR_FILES_AS_SOCKETS */ - -/* Create a dummy wakeup pipe for interrupting the poller - */ -static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset) -{ - apr_status_t rv; - - if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0], - &pollset->wakeup_pipe[1], - pollset->pool)) != APR_SUCCESS) - return rv; - - pollset->wakeup_pfd.p = pollset->pool; - pollset->wakeup_pfd.reqevents = APR_POLLIN; - pollset->wakeup_pfd.desc_type = APR_POLL_FILE; - pollset->wakeup_pfd.desc.f = pollset->wakeup_pipe[0]; - - { - int flags; - - if ((flags = fcntl(pollset->wakeup_pipe[0]->filedes, F_GETFD)) == -1) - return errno; - - flags |= FD_CLOEXEC; - if (fcntl(pollset->wakeup_pipe[0]->filedes, F_SETFD, flags) == -1) - return errno; - } - { - int flags; - - if ((flags = fcntl(pollset->wakeup_pipe[1]->filedes, F_GETFD)) == -1) - return errno; - - flags |= FD_CLOEXEC; - if (fcntl(pollset->wakeup_pipe[1]->filedes, F_SETFD, flags) == -1) - return errno; - } - - return apr_pollset_add(pollset, &pollset->wakeup_pfd); -} -#endif /* !APR_FILES_AS_SOCKETS */ - -/* Read and discard what's ever in the wakeup pipe. - */ -void apr_pollset_drain_wakeup_pipe(apr_pollset_t *pollset) -{ - char rb[512]; - apr_size_t nr = sizeof(rb); - - while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) { - /* Although we write just one byte to the other end of the pipe - * during wakeup, multiple threads could call the wakeup. - * So simply drain out from the input side of the pipe all - * the data. - */ - if (nr != sizeof(rb)) - break; - } -} - static apr_status_t pollset_cleanup(void *p) { apr_pollset_t *pollset = (apr_pollset_t *) p; @@ -132,48 +37,32 @@ static apr_status_t pollset_cleanup(void *p) (*pollset->provider->cleanup)(pollset); } if (pollset->flags & APR_POLLSET_WAKEABLE) { - /* Close both sides of the wakeup pipe */ - if (pollset->wakeup_pipe[0]) { -#if APR_FILES_AS_SOCKETS - apr_file_close(pollset->wakeup_pipe[0]); -#else - apr_file_socket_pipe_close(pollset->wakeup_pipe[0]); -#endif - pollset->wakeup_pipe[0] = NULL; - } - if (pollset->wakeup_pipe[1]) { -#if APR_FILES_AS_SOCKETS - apr_file_close(pollset->wakeup_pipe[1]); -#else - apr_file_socket_pipe_close(pollset->wakeup_pipe[1]); -#endif - pollset->wakeup_pipe[1] = NULL; - } + apr_poll_close_wakeup_pipe(pollset->wakeup_pipe); } return APR_SUCCESS; } #if defined(HAVE_KQUEUE) -extern apr_pollset_provider_t *apr_pollset_provider_kqueue; +extern const apr_pollset_provider_t *apr_pollset_provider_kqueue; #endif #if defined(HAVE_PORT_CREATE) -extern apr_pollset_provider_t *apr_pollset_provider_port; +extern const apr_pollset_provider_t *apr_pollset_provider_port; #endif #if defined(HAVE_EPOLL) -extern apr_pollset_provider_t *apr_pollset_provider_epoll; +extern const apr_pollset_provider_t *apr_pollset_provider_epoll; #endif #if defined(HAVE_AIO_MSGQ) -extern apr_pollset_provider_t *apr_pollset_provider_aio_msgq; +extern const apr_pollset_provider_t *apr_pollset_provider_aio_msgq; #endif #if defined(HAVE_POLL) -extern apr_pollset_provider_t *apr_pollset_provider_poll; +extern const apr_pollset_provider_t *apr_pollset_provider_poll; #endif -extern apr_pollset_provider_t *apr_pollset_provider_select; +extern const apr_pollset_provider_t *apr_pollset_provider_select; -static apr_pollset_provider_t *pollset_provider(apr_pollset_method_e method) +static const apr_pollset_provider_t *pollset_provider(apr_pollset_method_e method) { - apr_pollset_provider_t *provider = NULL; + const apr_pollset_provider_t *provider = NULL; switch (method) { case APR_POLLSET_KQUEUE: #if defined(HAVE_KQUEUE) @@ -217,7 +106,7 @@ APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **ret_pollset, { apr_status_t rv; apr_pollset_t *pollset; - apr_pollset_provider_t *provider = NULL; + const apr_pollset_provider_t *provider = NULL; *ret_pollset = NULL; @@ -276,7 +165,13 @@ APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **ret_pollset, } if (flags & APR_POLLSET_WAKEABLE) { /* Create wakeup pipe */ - if ((rv = create_wakeup_pipe(pollset)) != APR_SUCCESS) { + if ((rv = apr_poll_create_wakeup_pipe(pollset->pool, &pollset->wakeup_pfd, + pollset->wakeup_pipe)) + != APR_SUCCESS) { + return rv; + } + + if ((rv = apr_pollset_add(pollset, &pollset->wakeup_pfd)) != APR_SUCCESS) { return rv; } } @@ -295,7 +190,7 @@ APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset) APR_DECLARE(const char *) apr_poll_method_defname() { - apr_pollset_provider_t *provider = NULL; + const apr_pollset_provider_t *provider = NULL; provider = pollset_provider(pollset_default_method); if (provider) diff --git a/poll/unix/port.c b/poll/unix/port.c index 5002dfdbe24c..94b6fa3978d5 100644 --- a/poll/unix/port.c +++ b/poll/unix/port.c @@ -354,12 +354,13 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, const apr_pollfd_t **descriptors) { apr_os_sock_t fd; - int ret, i, j; - unsigned int nget; + int ret; + unsigned int nget, i; + apr_int32_t nres = 0; pfd_elem_t *ep; apr_status_t rv = APR_SUCCESS; - apr_pollfd_t fp; + *num = 0; nget = 1; pollset_lock_rings(); @@ -403,49 +404,41 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, port_associate within apr_pollset_add() */ apr_atomic_dec32(&pollset->p->waiting); - (*num) = nget; - if (nget) { - - pollset_lock_rings(); + pollset_lock_rings(); - for (i = 0, j = 0; i < nget; i++) { - fp = (((pfd_elem_t*)(pollset->p->port_set[i].portev_user))->pfd); - if ((pollset->flags & APR_POLLSET_WAKEABLE) && - fp.desc_type == APR_POLL_FILE && - fp.desc.f == pollset->wakeup_pipe[0]) { - apr_pollset_drain_wakeup_pipe(pollset); - rv = APR_EINTR; - } - else { - pollset->p->result_set[j] = fp; - pollset->p->result_set[j].rtnevents = - get_revent(pollset->p->port_set[i].portev_events); - - /* If the ring element is still on the query ring, move it - * to the add ring for re-association with the event port - * later. (It may have already been moved to the dead ring - * by a call to pollset_remove on another thread.) - */ - ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user; - if (ep->on_query_ring) { - APR_RING_REMOVE(ep, link); - ep->on_query_ring = 0; - APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep, - pfd_elem_t, link); - } - j++; - } + for (i = 0; i < nget; i++) { + ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user; + if ((pollset->flags & APR_POLLSET_WAKEABLE) && + ep->pfd.desc_type == APR_POLL_FILE && + ep->pfd.desc.f == pollset->wakeup_pipe[0]) { + apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe); + rv = APR_EINTR; } - pollset_unlock_rings(); - if ((*num = j)) { /* any event besides wakeup pipe? */ - rv = APR_SUCCESS; - if (descriptors) { - *descriptors = pollset->p->result_set; - } + else { + pollset->p->result_set[nres] = ep->pfd; + pollset->p->result_set[nres].rtnevents = + get_revent(pollset->p->port_set[i].portev_events); + ++nres; + } + /* If the ring element is still on the query ring, move it + * to the add ring for re-association with the event port + * later. (It may have already been moved to the dead ring + * by a call to pollset_remove on another thread.) + */ + if (ep->on_query_ring) { + APR_RING_REMOVE(ep, link); + ep->on_query_ring = 0; + APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep, + pfd_elem_t, link); + } + } + if (nres > 0) { /* any event besides wakeup pipe? */ + *num = nres; + rv = APR_SUCCESS; + if (descriptors) { + *descriptors = pollset->p->result_set; } } - - pollset_lock_rings(); /* Shift all PFDs in the Dead Ring to the Free Ring */ APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link); @@ -455,7 +448,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, return rv; } -static apr_pollset_provider_t impl = { +static const apr_pollset_provider_t impl = { impl_pollset_create, impl_pollset_add, impl_pollset_remove, @@ -464,11 +457,10 @@ static apr_pollset_provider_t impl = { "port" }; -apr_pollset_provider_t *apr_pollset_provider_port = &impl; +const apr_pollset_provider_t *apr_pollset_provider_port = &impl; -static apr_status_t cb_cleanup(void *p_) +static apr_status_t impl_pollcb_cleanup(apr_pollcb_t *pollcb) { - apr_pollcb_t *pollcb = (apr_pollcb_t *) p_; close(pollcb->fd); return APR_SUCCESS; } @@ -505,7 +497,6 @@ static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb, } pollcb->pollset.port = apr_palloc(p, size * sizeof(port_event_t)); - apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null); return APR_SUCCESS; } @@ -558,16 +549,25 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, apr_pollcb_cb_t func, void *baton) { - apr_pollfd_t *pollfd; apr_status_t rv; - unsigned int i, nget = 1; + unsigned int nget = 1; rv = call_port_getn(pollcb->fd, pollcb->pollset.port, pollcb->nalloc, &nget, timeout); if (nget) { + unsigned int i; + for (i = 0; i < nget; i++) { - pollfd = (apr_pollfd_t *)(pollcb->pollset.port[i].portev_user); + apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.port[i].portev_user); + + if ((pollcb->flags & APR_POLLSET_WAKEABLE) && + pollfd->desc_type == APR_POLL_FILE && + pollfd->desc.f == pollcb->wakeup_pipe[0]) { + apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe); + return APR_EINTR; + } + pollfd->rtnevents = get_revent(pollcb->pollset.port[i].portev_events); rv = func(baton, pollfd); @@ -581,14 +581,15 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, return rv; } -static apr_pollcb_provider_t impl_cb = { +static const apr_pollcb_provider_t impl_cb = { impl_pollcb_create, impl_pollcb_add, impl_pollcb_remove, impl_pollcb_poll, + impl_pollcb_cleanup, "port" }; -apr_pollcb_provider_t *apr_pollcb_provider_port = &impl_cb; +const apr_pollcb_provider_t *apr_pollcb_provider_port = &impl_cb; #endif /* HAVE_PORT_CREATE */ diff --git a/poll/unix/select.c b/poll/unix/select.c index 61a064f469bb..51be3c1cd5f9 100644 --- a/poll/unix/select.c +++ b/poll/unix/select.c @@ -347,13 +347,14 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, fd_set readset, writeset, exceptset; apr_status_t rv = APR_SUCCESS; + *num = 0; + #ifdef WIN32 /* On Win32, select() must be presented with at least one socket to * poll on, or select() will return WSAEINVAL. So, we'll just * short-circuit and bail now. */ if (pollset->nelts == 0) { - (*num) = 0; if (timeout > 0) { apr_sleep(timeout); return APR_TIMEUP; @@ -385,7 +386,6 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, rs = select(pollset->p->maxfd + 1, &readset, &writeset, &exceptset, tvptr); - (*num) = rs; if (rs < 0) { return apr_get_netos_error(); } @@ -401,7 +401,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, else { if ((pollset->flags & APR_POLLSET_WAKEABLE) && pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) { - apr_pollset_drain_wakeup_pipe(pollset); + apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe); rv = APR_EINTR; continue; } @@ -437,7 +437,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, return rv; } -static apr_pollset_provider_t impl = { +static const apr_pollset_provider_t impl = { impl_pollset_create, impl_pollset_add, impl_pollset_remove, @@ -446,4 +446,4 @@ static apr_pollset_provider_t impl = { "select" }; -apr_pollset_provider_t *apr_pollset_provider_select = &impl; +const apr_pollset_provider_t *apr_pollset_provider_select = &impl; diff --git a/poll/unix/wakeup.c b/poll/unix/wakeup.c new file mode 100644 index 000000000000..acf8afc97a27 --- /dev/null +++ b/poll/unix/wakeup.c @@ -0,0 +1,151 @@ +/* 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_file_io.h" +#include "apr_arch_networkio.h" +#include "apr_arch_poll_private.h" +#include "apr_arch_inherit.h" + +#if !APR_FILES_AS_SOCKETS + +#ifdef WIN32 + +apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd, + apr_file_t **wakeup_pipe) +{ + apr_status_t rv; + + if ((rv = apr_file_socket_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1], + pool)) != APR_SUCCESS) + return rv; + + pfd->reqevents = APR_POLLIN; + pfd->desc_type = APR_POLL_FILE; + pfd->desc.f = wakeup_pipe[0]; + return APR_SUCCESS; +} + +apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe) +{ + apr_status_t rv0 = APR_SUCCESS; + apr_status_t rv1 = APR_SUCCESS; + + /* Close both sides of the wakeup pipe */ + if (wakeup_pipe[0]) { + rv0 = apr_file_socket_pipe_close(wakeup_pipe[0]); + wakeup_pipe[0] = NULL; + } + if (wakeup_pipe[1]) { + rv1 = apr_file_socket_pipe_close(wakeup_pipe[1]); + wakeup_pipe[1] = NULL; + } + return rv0 ? rv0 : rv1; +} + +#else /* !WIN32 */ + +apr_status_t apr_poll_create_wakeup_pipe(apr_pollfd_t *pfd, apr_file_t **wakeup_pipe) +{ + return APR_ENOTIMPL; +} + +apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe) +{ + return APR_ENOTIMPL; +} + +#endif /* !WIN32 */ + +#else /* APR_FILES_AS_SOCKETS */ + +apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd, + apr_file_t **wakeup_pipe) +{ + apr_status_t rv; + + if ((rv = apr_file_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1], + pool)) != APR_SUCCESS) + return rv; + + pfd->p = pool; + pfd->reqevents = APR_POLLIN; + pfd->desc_type = APR_POLL_FILE; + pfd->desc.f = wakeup_pipe[0]; + + { + int flags; + + if ((flags = fcntl(wakeup_pipe[0]->filedes, F_GETFD)) == -1) + return errno; + + flags |= FD_CLOEXEC; + if (fcntl(wakeup_pipe[0]->filedes, F_SETFD, flags) == -1) + return errno; + } + { + int flags; + + if ((flags = fcntl(wakeup_pipe[1]->filedes, F_GETFD)) == -1) + return errno; + + flags |= FD_CLOEXEC; + if (fcntl(wakeup_pipe[1]->filedes, F_SETFD, flags) == -1) + return errno; + } + + return APR_SUCCESS; +} + +apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe) +{ + apr_status_t rv0 = APR_SUCCESS; + apr_status_t rv1 = APR_SUCCESS; + + /* Close both sides of the wakeup pipe */ + if (wakeup_pipe[0]) { + rv0 = apr_file_close(wakeup_pipe[0]); + wakeup_pipe[0] = NULL; + } + if (wakeup_pipe[1]) { + rv1 = apr_file_close(wakeup_pipe[1]); + wakeup_pipe[1] = NULL; + } + return rv0 ? rv0 : rv1; +} + +#endif /* APR_FILES_AS_SOCKETS */ + +/* Read and discard whatever is in the wakeup pipe. + */ +void apr_poll_drain_wakeup_pipe(apr_file_t **wakeup_pipe) +{ + char rb[512]; + apr_size_t nr = sizeof(rb); + + while (apr_file_read(wakeup_pipe[0], rb, &nr) == APR_SUCCESS) { + /* Although we write just one byte to the other end of the pipe + * during wakeup, multiple threads could call the wakeup. + * So simply drain out from the input side of the pipe all + * the data. + */ + if (nr != sizeof(rb)) + break; + } +} diff --git a/poll/unix/z_asio.c b/poll/unix/z_asio.c index 7e0fd89a549c..48b531cc8c74 100644 --- a/poll/unix/z_asio.c +++ b/poll/unix/z_asio.c @@ -247,9 +247,11 @@ static apr_status_t asio_pollset_cleanup(apr_pollset_t *pollset) int rv; DBG(4, "entered\n"); - rv = msgctl(pollset->p->msg_q, IPC_RMID, NULL); + if (pollset->flags & APR_POLLSET_THREADSAFE) { + rv = msgctl(pollset->p->msg_q, IPC_RMID, NULL); + DBG1(4, "asio_pollset_cleanup: msgctl(IPC_RMID) returned %d\n", rv); + } - DBG1(4, "exiting, msgctl(IPC_RMID) returned %d\n", rv); return rv; } @@ -264,13 +266,13 @@ static apr_status_t asio_pollset_create(apr_pollset_t *pollset, DBG1(2, "entered, flags: %x\n", flags); - priv = pollset->p = apr_palloc(p, sizeof(*priv)); + priv = pollset->p = apr_pcalloc(p, sizeof(*priv)); if (flags & APR_POLLSET_THREADSAFE) { #if APR_HAS_THREADS - if (rv = apr_thread_mutex_create(&(priv->ring_lock), + if ((rv = apr_thread_mutex_create(&(priv->ring_lock), APR_THREAD_MUTEX_DEFAULT, - p) != APR_SUCCESS) { + p)) != APR_SUCCESS) { DBG1(1, "apr_thread_mutex_create returned %d\n", rv); pollset->p = NULL; return rv; @@ -481,7 +483,8 @@ static apr_status_t asio_pollset_remove(apr_pollset_t *pollset, asio_elem_t *elem; apr_status_t rv = APR_SUCCESS; apr_pollset_private_t *priv = pollset->p; - struct aiocb cancel_a; /* AIO_CANCEL is synchronous, so autodata works fine */ + /* AIO_CANCEL is synchronous, so autodata works fine. */ + struct aiocb cancel_a = {0}; int fd; @@ -765,7 +768,7 @@ static apr_status_t asio_pollset_poll(apr_pollset_t *pollset, return rv; } /* end of asio_pollset_poll */ -static apr_pollset_provider_t impl = { +static const apr_pollset_provider_t impl = { asio_pollset_create, asio_pollset_add, asio_pollset_remove, @@ -774,6 +777,6 @@ static apr_pollset_provider_t impl = { "asio" }; -apr_pollset_provider_t *apr_pollset_provider_aio_msgq = &impl; +const apr_pollset_provider_t *apr_pollset_provider_aio_msgq = &impl; #endif /* HAVE_AIO_MSGQ */ |