diff options
author | niq <niq@13f79535-47bb-0310-9956-ffa450edef68> | 2008-05-13 22:02:52 +0000 |
---|---|---|
committer | niq <niq@13f79535-47bb-0310-9956-ffa450edef68> | 2008-05-13 22:02:52 +0000 |
commit | 7f4e0ed8a2500d1c68a213d030af9278199f3f3c (patch) | |
tree | 6625a5d0d6d35866d1df3859f8b8b3aa303e7b88 | |
parent | 8e2350ed8dd8c6145c59413f714681bb681ac1df (diff) | |
download | libapr-7f4e0ed8a2500d1c68a213d030af9278199f3f3c.tar.gz |
Backport Henry Jen's fix for Solaris poll failure [PR43000]
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/branches/1.3.x@656028 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | poll/unix/port.c | 35 |
2 files changed, 31 insertions, 7 deletions
@@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes for APR 1.3.0 + *) Fix Solaris poll failure. PR 43000 + [Henry Jen <henryjen ztune.net>] + *) apr_getservbyname(): Use proper method for converting port to host byte order. PR 44903. [Chris Taylor <ctaylor wadeford.plus.com>] diff --git a/poll/unix/port.c b/poll/unix/port.c index 05848d618..6f0ce7552 100644 --- a/poll/unix/port.c +++ b/poll/unix/port.c @@ -15,6 +15,7 @@ */ #include "apr_arch_poll_private.h" +#include "apr_atomic.h" #ifdef POLLSET_USES_PORT @@ -80,6 +81,8 @@ struct apr_pollset_t /* A ring of pollfd_t where rings that have been _remove'd but might still be inside a _poll */ APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring; + /* number of threads in poll */ + volatile apr_uint32_t waiting; }; static apr_status_t backend_cleanup(void *p_) @@ -110,6 +113,7 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, return APR_ENOTIMPL; } #endif + (*pollset)->waiting = 0; (*pollset)->nelts = 0; (*pollset)->nalloc = size; (*pollset)->flags = flags; @@ -168,16 +172,22 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, fd = descriptor->desc.f->filedes; } - res = port_associate(pollset->port_fd, PORT_SOURCE_FD, fd, - get_event(descriptor->reqevents), (void *)elem); + if (apr_atomic_read32(&pollset->waiting)) { + res = port_associate(pollset->port_fd, PORT_SOURCE_FD, fd, + get_event(descriptor->reqevents), (void *)elem); - if (res < 0) { - rv = APR_ENOMEM; - APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); - } + if (res < 0) { + rv = APR_ENOMEM; + APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); + } + else { + pollset->nelts++; + APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); + } + } else { pollset->nelts++; - APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); + APR_RING_INSERT_TAIL(&(pollset->add_ring), elem, pfd_elem_t, link); } pollset_unlock_rings(); @@ -192,6 +202,7 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, pfd_elem_t *ep; apr_status_t rv = APR_SUCCESS; int res; + int err; pollset_lock_rings(); @@ -205,6 +216,7 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, res = port_dissociate(pollset->port_fd, PORT_SOURCE_FD, fd); if (res < 0) { + err = errno; rv = APR_NOTFOUND; } @@ -233,6 +245,9 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, APR_RING_REMOVE(ep, link); APR_RING_INSERT_TAIL(&(pollset->dead_ring), ep, pfd_elem_t, link); + if (ENOENT == err) { + rv = APR_SUCCESS; + } break; } } @@ -268,6 +283,8 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, pollset_lock_rings(); + apr_atomic_inc32(&pollset->waiting); + while (!APR_RING_EMPTY(&(pollset->add_ring), pfd_elem_t, link)) { ep = APR_RING_FIRST(&(pollset->add_ring)); APR_RING_REMOVE(ep, link); @@ -291,6 +308,9 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, ret = port_getn(pollset->port_fd, pollset->port_set, pollset->nalloc, &nget, tvptr); + /* decrease the waiting ASAP to reduce the window for calling + port_associate within apr_pollset_add() */ + apr_atomic_dec32(&pollset->waiting); (*num) = nget; if (ret == -1) { @@ -459,6 +479,7 @@ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, if (rv) { return rv; } + rv = apr_pollcb_add(pollcb, pollfd); } } |