summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorniq <niq@13f79535-47bb-0310-9956-ffa450edef68>2008-05-13 22:02:52 +0000
committerniq <niq@13f79535-47bb-0310-9956-ffa450edef68>2008-05-13 22:02:52 +0000
commit7f4e0ed8a2500d1c68a213d030af9278199f3f3c (patch)
tree6625a5d0d6d35866d1df3859f8b8b3aa303e7b88
parent8e2350ed8dd8c6145c59413f714681bb681ac1df (diff)
downloadlibapr-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--CHANGES3
-rw-r--r--poll/unix/port.c35
2 files changed, 31 insertions, 7 deletions
diff --git a/CHANGES b/CHANGES
index ef7ce02b5..3256dd150 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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);
}
}