summaryrefslogtreecommitdiff
path: root/poll
diff options
context:
space:
mode:
Diffstat (limited to 'poll')
-rw-r--r--poll/unix/epoll.c43
-rw-r--r--poll/unix/kqueue.c44
-rw-r--r--poll/unix/poll.c28
-rw-r--r--poll/unix/pollcb.c63
-rw-r--r--poll/unix/pollset.c141
-rw-r--r--poll/unix/port.c105
-rw-r--r--poll/unix/select.c10
-rw-r--r--poll/unix/wakeup.c151
-rw-r--r--poll/unix/z_asio.c19
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 */