summaryrefslogtreecommitdiff
path: root/poll
diff options
context:
space:
mode:
authortrawick <trawick@13f79535-47bb-0310-9956-ffa450edef68>2009-08-24 15:03:57 +0000
committertrawick <trawick@13f79535-47bb-0310-9956-ffa450edef68>2009-08-24 15:03:57 +0000
commitc93beb0fd300abb9699c136d73519a62bded1e1f (patch)
treefdb50436c8b30ac08dde9342a83dc7f77e4fb8ef /poll
parent4918152cecd1d54c8c2ee528e94d876e27939faf (diff)
downloadlibapr-c93beb0fd300abb9699c136d73519a62bded1e1f.tar.gz
backport r807263 from trunk:
Fix an error handling issue in the Event Port backend for APR pollsets. (ETIME is sometimes reported along with an event.) PR: 47645 git-svn-id: http://svn.apache.org/repos/asf/apr/apr/branches/1.4.x@807265 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'poll')
-rw-r--r--poll/unix/port.c112
1 files changed, 60 insertions, 52 deletions
diff --git a/poll/unix/port.c b/poll/unix/port.c
index f7fd03bb1..c5d98749e 100644
--- a/poll/unix/port.c
+++ b/poll/unix/port.c
@@ -85,6 +85,58 @@ struct apr_pollset_t
volatile apr_uint32_t waiting;
};
+static apr_status_t call_port_getn(int port, port_event_t list[],
+ unsigned int max, unsigned int *nget,
+ apr_interval_time_t timeout)
+{
+ struct timespec tv, *tvptr;
+ int ret;
+ apr_status_t rv = APR_SUCCESS;
+
+ if (timeout < 0) {
+ tvptr = NULL;
+ }
+ else {
+ tv.tv_sec = (long) apr_time_sec(timeout);
+ tv.tv_nsec = (long) apr_time_usec(timeout) * 1000;
+ tvptr = &tv;
+ }
+
+ ret = port_getn(port, list, max, nget, tvptr);
+
+ if (ret < 0) {
+ rv = apr_get_netos_error();
+
+ switch(rv) {
+ case EINTR:
+ case ETIME:
+ if (*nget > 0) {
+ /* This confusing API can return an event at the same time
+ * that it reports EINTR or ETIME. If that occurs, just
+ * report the event.
+ * (Maybe it will be simplified; see thread
+ * http://mail.opensolaris.org
+ * /pipermail/networking-discuss/2009-August/011979.html
+ * This code will still work afterwards.)
+ */
+ rv = APR_SUCCESS;
+ break;
+ }
+ if (rv == ETIME) {
+ rv = APR_TIMEUP;
+ }
+ /* fall-through */
+ default:
+ *nget = 0;
+ }
+ }
+ else if (*nget == 0) {
+ rv = APR_TIMEUP;
+ }
+
+ return rv;
+}
+
static apr_status_t backend_cleanup(void *p_)
{
apr_pollset_t *pollset = (apr_pollset_t *) p_;
@@ -337,19 +389,9 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
int ret, i, j;
unsigned int nget;
pfd_elem_t *ep;
- struct timespec tv, *tvptr;
apr_status_t rv = APR_SUCCESS;
apr_pollfd_t fp;
- if (timeout < 0) {
- tvptr = NULL;
- }
- else {
- tv.tv_sec = (long) apr_time_sec(timeout);
- tv.tv_nsec = (long) apr_time_usec(timeout) * 1000;
- tvptr = &tv;
- }
-
nget = 1;
pollset_lock_rings();
@@ -385,27 +427,15 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
return rv;
}
- ret = port_getn(pollset->port_fd, pollset->port_set, pollset->nalloc,
- &nget, tvptr);
+ rv = call_port_getn(pollset->port_fd, pollset->port_set, pollset->nalloc,
+ &nget, timeout);
/* 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) {
- (*num) = 0;
- if (errno == ETIME) {
- rv = APR_TIMEUP;
- }
- else {
- rv = apr_get_netos_error();
- }
- }
- else if (nget == 0) {
- rv = APR_TIMEUP;
- }
- else {
+ (*num) = nget;
+ if (nget) {
pollset_lock_rings();
@@ -554,36 +584,14 @@ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
apr_pollcb_cb_t func,
void *baton)
{
- int ret;
apr_pollfd_t *pollfd;
- struct timespec tv, *tvptr;
- apr_status_t rv = APR_SUCCESS;
+ apr_status_t rv;
unsigned int i, nget = pollcb->nalloc;
- if (timeout < 0) {
- tvptr = NULL;
- }
- else {
- tv.tv_sec = (long) apr_time_sec(timeout);
- tv.tv_nsec = (long) apr_time_usec(timeout) * 1000;
- tvptr = &tv;
- }
+ rv = call_port_getn(pollcb->port_fd, pollcb->port_set, pollcb->nalloc,
+ &nget, timeout);
- ret = port_getn(pollcb->port_fd, pollcb->port_set, pollcb->nalloc,
- &nget, tvptr);
-
- if (ret == -1) {
- if (errno == ETIME) {
- rv = APR_TIMEUP;
- }
- else {
- rv = apr_get_netos_error();
- }
- }
- else if (nget == 0) {
- rv = APR_TIMEUP;
- }
- else {
+ if (nget) {
for (i = 0; i < nget; i++) {
pollfd = (apr_pollfd_t *)(pollcb->port_set[i].portev_user);
pollfd->rtnevents = get_revent(pollcb->port_set[i].portev_events);